0% found this document useful (0 votes)
20 views722 pages

Programmer's Guide To The OS2 Presentation Manager

Uploaded by

quantum_22
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views722 pages

Programmer's Guide To The OS2 Presentation Manager

Uploaded by

quantum_22
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 722

• Functions and Messages by category

Note.. The following is a list of all OS |2 and Presentation Manager functions and messages discussed
in the book, organized according to the types of services they provide. Following the name of each
function or message is the number of the figure in the book that provides a full explanation.

• CLIPBOARD Menus
MANAGEMENT MM SETITEMTEXT
Winopenclipbrd MM SETITEMATTR
WinQueryclipbrdData WM INITMENU
WinsetclipbrdData
Scroll Bars
WinEmptyclipbrd
SBM SETSCROLLBAR
Wincloseclipbrd
SBM SETPOS
WM HSCROLL
WM VSCROLL
• COMMUNICATION
(AMONG THREADS)
Dossemset 12.6 . CURSOR
Dossemclear 12.7
MANAGEMENT
Dossemwait 12.8
Wincreatecursor
Winshowcursor
WinDestroycursor
CONTROL WINDOW
MANAGEMENT
General • DIALOGBOX
WM COMRAND MANAGEMENT
WM CONTROL WinDlgBox
WinDefDlgproc
Edit Fields
WinsendDlgltemMsg
- EM SETTEXTLIMIT 8.24
WinDismissDlg
List Boxes WM INITDLG
LM INSERTITEM
LM_QUERYSELECTION
LM_QUERYITEMTEXT
LM DELETEALL
• DISPLAYOFDATA WinMessageBox
WinAlarm
Erasing
WinFillRect
GpiErase
• INFORMATION
WM ERASEBACKGROUND
Winquerysysvalue 11.1
Font Management
GpicreateLogFont
GpiLoadFonts
• INITIALIZATION /
GpiQueryFonts
Gpisetcharset TERMINATION
Winlnitialize
Graphics WincreateMsgQueue
GpiMOve WinRegisterclass
GpiLine WinDestroyMsgqueue
WinDrawBitmap WinTerminate
WinDrawpointer WM CREATE
WM INITDLG
Miscellanous
WM CLOSE
Winscrollwindow
WM_QUIT
Winupdatewindow
WM DESTROY
WM PAINT

Presentation Spaces
WinlnvalidateRect • KEYBOARD
WinBeginpaint MANAGEMENT
WinEndpaint WinGetKeystate
WinGetps WinQueryFocus
WinReleaseps
WinsetFocus
Text Strings / Attributes WM CHAR
WM SETFOCUS
Gpisetcolor
GpisetBackcolor
GpisetBackMix
GpicharstringAt • MEMORY
WinDrawText MANAGEMENT
Winupper
Heap
WincreateHeap
WinLockHeap
• ERROR PROCHSSING WinAlocMem
WinGetLastError 3.11 WinFreeMem
WinDestroyHeap
.P rogrammer's Guide
to the OS/2
Presentation Manager
.P rogranmer'S Guide
to the os/rM
Presentation Manager

Michael J. Young

£EN®
Sam Francisco . Paris . Dtisseldorf . London
Cover design by Thomas Ingans + Associates
Cover photography by David Bishop
Book design by Ingrid Owen
Illustrations by Jeffrey James Giese

IBM is a trademark of International Business Machines Corporation.


Intel is a trademark of Intel Corporation.
Microsoft C, Microsoft Windows, MS, OS/2, and Windows Presentation Manager are trademarks of
Microsoft Corporation.

SYBEX is a registered trademark and Prompter Series is a trademark of SYBEX, Inc.

SYBEX is not affiliated with any manufacturer.

Every effort has been made to supply complete and accurate information. However, SYBEX assumes
no responsibility for its use, nor for any infringements of patents or other rights of third parties which
would result.

Copyright©1989 SYBEX inc., 2021 Challenger Drive # 100, Alameda, CA 94501. World rights reserved.
No part of this publication may be stored in a retrieval system, transmitted, or reproduced in any way,
including but not limited to photocopy, photograph, magnetic or other record, without prior agree-
ment and written permission of the publisher.

Library of Congress Card Number: 8842827


ISBN 0-89588-569-7
Manufactured in the United States of America
10 9 8 7 6 5 4 3 2 1
.rF o the memory of my father
• Acknowledgments

Writing this book for SYBEX was, as always, an enjoyable and reward-
ing experience. Both Rudolph Langer, editor-in{hief, and Dianne King,
acquisitions editor, were receptive to my ideas and supportive of my
needs as I developed the book. Tanya Kucak, editor, deserves special
thanks for editing the entire manuscript and greatly enhancing the con-
sisteney of the style. I also enjoyed working with Robert Campbell,
technical editor, who caught more than one subtle bug in the example
programs. Byron Dazey, of Microsoft Corporation, was of immense
help during the final stages of preparing the manuscript; his technical
review enhanced the accuracy of the text and helped ensure that the ex-
ample programs would run successfully under the final release of the
system. I would also like to thank the other people at SYBEX who con-
tributed to this project: Ingrid Owen, design and layout; Jocelyn
Reynolds and Bob Myren, word processing; Sonja Schenk, screen
reproductions; Charles Cowens, desktop publishing; and Jeffrey James
Giese, illustrations. Finally, the developers at Microsoft and IBM
deserve much credit for creating the impressive system that is the sub-
ject of this book.
ontents At a Glance
.C
Introduction xvii

Pflr£ I.. Basic Features 1

Cfe¢pfcr o7zc.. Orientation 2

Chapfcr fztJo.. Creating a Window 26

Cfe¢pfer ffe7`cc.. Managing Memory 80

Cfe¢pfcr /o#r.. Using Scroll Bars 146

Cfe¢pfcr ¢.z7c.. Controlling the Cursor 198

Cfeczpfcr s!.x.. Adding a Keyboard Interface 226

Cfe¢pfer sezJc7i.. Using Menus and Accelerators 300

Cfe¢pfer c!.gfef.. Designing Dialog Boxes 336

Pczr£ JJ.. Advanced Features 459

Cfe¢pfcr 7".7zc.. Interfacing with the Clipboard 460

Cfeflpfcr fc7i.. Creating Icons, Bitmaps, and Other Resources 490

CJz¢pfcr cJcz7c77.. Adding a Mouse Interface 534

Cfe¢pfcr fztJeJZJc.. Exploiting Multitasking and Inteaprocess Communication 582

Appendix a: Glossairy 610

Appc71dz.x Z7.. Selected Presentation Manager Functions 630

Appc7zd!.x c.. Selected Presentation Manager Messages 666

Bivliograpky 674

Index FJJ17
.T able of Contents
Introduction

PART I: BASIC FEATURES

hapter one
Orientation
OS/2Features 3
ScreenGroups 3
Multitasking and Interprocess communication 6
Virtual Memory 7
Dynamic Linking 11
Presentation Manager Features 18
The user Interface shell 18
Types of Programs Managed by the Presentation
Manager 21
The presentation Manager API 24 I

Conclusion 25

hapter two
Creating a Window 26
Becoming a presentation Manager Application 27
Step 1: Initialize the presentation Manager 28
Step 2: Create a Message Queue 33
Step 3: Registera window class 34
Step4: Createawindow 38
Step 5: Get and Dispatch Messages 49
Step 6: Release presentation Manager Resources 57
Processing Messages 58
•xii

Displaying Data within the window 61


When the wM_PAINT Message Is sent 61
Steps for updating the screen 65
Building a presentation Manager Application 72

hapter three
Managing Memory 80
Managing the Heap 83
Handling Errors 101
Displaying Text 113
The wM_SIZE Message 123
The wM_PAINT Message 124
Enhancements 133
Conclusion 135

Chapter four
Using Scroll Bars 146
Creating the scroll Bars 147
The wM_CREATE Message 151
The wM_SIZE Message 155
Processing the scroll Bar Messages 163
The wM_HSCROLL Message 163
The wM_VSCROLL Message 174
Rerouting Keyboard Input 179
Updating the window 180
Enhancements 184
Conclusion 185

Chapter five
Controlling the Cursor 198
Creating the cursor 200
xiii .

Maintaining the cursor 208


Keeping the Insertion point within the window 208
Recreating the cursor 211
Moving the cursor 213
The cursor-Movement Keys 214
TheHomeandEndKeys 218
Moving the cursor when scrolling 221
Conclusion 224

hapter six
Adding a Keyboard Interface 226
The wM_CHAR Message 227
Thescancode 231
The charactercode 231
The virtual-Key code 231
TheRepeatcount 232
The Keyboard control Flags 235
The character Keys 236
Normal character Keys 241
TheTabKey 248
TheEnterKey 249
The Backspace Key 252
ThevirfualKeys 259
TheF9Key 260
TheDelKey 262
ThelnsKey 262
Editing aNewFile 264
Enhancements 265
Inline Display code 266
Eliminating Trailing Blanks 267
Converting Tab characters 268
Conclusion 268
•xiv

hapter seven
Using Menus and Accelerators 300
Creating Menus and Accelerators 301
Managing Menus and Accelerators 311
The wM_INITMENU Message 311
The wM_COMMAND Message 318
The wM_HELP Message 320
TheMenu commands 322
TheNewcommand 322
The save command 330
The Exitcommand 333
The Insert/Overwrite Mode command 333
Enhancements 334
Conclusion 335

hapter eight
Designing Dialog Boxes 336
Creating a Dialog Box 337
Using the Dialog Box Editor 338
The program Dialog Boxes 343
Displaying a Dialog Box 354
Managing a Dialog Box 356
Thecommands 359
TheAboutcommand 360
The Find and Find Next commands 362
TheGotoLinecommand 372
ThesaveAscominand 375
The open command 380
Conclusion 396
XV®

PART 11: ADVANCED FEATURES 459

hapter nine
Interfacing with the Clipboard 460

Adding Data to the clipboard 461


Allocate a Memory segment 462
CopytheData 463
Open the clipboard 466
Insert the Data segment into the clipboard 468
Close the clipboard 472
Accessing Data in the clipboard 473
Open the clipboard 474
Obtain the Address of the Block 474
Secure Access to the shared Memory segment 476
Process orcopy the Block 478
Close the clipboard 478
Implementing a clipboard Interface 479
Other Features of the clipboard 485
Alternative clipboard Formats 486
The clipboard viewer window 487
Delayed Rendering of clipboard Data 488

hapter ten
Creating Icons, Bitmaps, and Other Resources 490

Icons and pointers 491


Designingan Icon 498
Installing an Icon 500
Displaying an Icon within the client window 502
Displaying an Icon within a Dialog Box 510
Designing a Mouse pointer 512
Bitmaps 512
Other Resources 526
•xvi

Strings 526
Programmer-Defined Resource Types 529

hapter eleven
Adding a Mouse Interface 534
Finding the Mouse pointer Location 535
Setting the Mouse pointer shape 547
Reading the Mouse Buttons 562
Creating a Mouse Interface 577
Mousecommands 578

hapter twelve
Exploiting Multitasking and Inteaprocess Communication 582
Using a second Thread 584
Starting the Thread 585
Writing a Function for a New Thread 590
Communicating between Threads 594
Using semaphores and Global variables 594
Using Messages 606

AIPpendi a
Glossary 610

Hppendib
Selected Presentation Manager Functions 630

PIPpenditc
Selected Presentation Manager Messages

Bibliography
Index
xvii .

.I ntroduction
The Presentation Manager is the windowed graphics interface
provided with the OS/2 operating system, beginning with version 1.1.
Although implemented as an extension to the basic operating system,
the Presentation Manager is central to the purpose of OS/2. OS/2 was
designed to run multiple programs, to allow communication among
these programs, and to provide efficient interaction with the user. The
Presentation Manager uses the basic facilities of OS/2 to run multiple
applications within windows on a single screen, to exchange data
among these applications, and to coordinate their input and output
operations. The Presentation Manager thus realizes the fundamental
design goals of OS/2; it fully exploits the basic operating-system
capabilities and makes these features immediately available to the
programmer and to the user. The designers of OS/2 consider the
Presentation Manager to be the OS/2 programming environment of
choice.
Writing an application for the Presentation Manager offers many ad-
vantages. First, the Presentation Manager uses a graphics display
mode, which can display a higher density of information than a stand-
ard text mode. The Presentation Manager is an ideal environment for
graphics programs, or for programs that display a combination of
graphics and text. Even applications that are primarily textual can
benefit from running in a graphics environment. These programs can
display text in a variety of fonts to produce a screen image that closely
resembles the final printed copy; also, a graphics display mode enables
the Presentation Manager to create the detailed icons and window ele-
ments that auow the user to control the program.
Another important advantage of the Presentation Manager is that the
graphics interface is #7i!/or77t from one apphcation to another. The Presen-
tation Manager provides a standard set of menus, dialog boxes, icons, and
other components of the user interface. Applications that use these stand-
ardfachitieshaveafamiliarappearanceandareeasytolean.Theinterface
is uniform not ordy among Presentation Manager applications, but also
among apphcations written for similar environments, such as Microsoft
Windows for MS-DOS. Additionally, by using these high-level fachities in
• xviii

your programs, you can avoid the significant programming effort re-
quired to develop your own user interface.
The Presentation Manager also provides uniform channels for com-
munication and exchange of data among separate programs. Accord-
ingly, applications written for this environment can easily coordinate
their activities and exchange data in order to form integrated software
Systems.
Finally, under the Presentation Manager you can write programs that
are dcz„.cc-z.77dcpc71dc7if (provided you follow the simple rules empha-
sized in this book). For example, you can write a Presentation Manager
application that will continue to run without modification as higher-
resolution video devices are developed in the future (assuming only
that the vendors of such devices supply the required device drivers for
the Presentation Manager).
Note also that the Presentation Manager forms an integral part of
OS/2. Unlike Microsoft Windows, the Presentation Manager is in-
cluded with every copy of the operating system ®eginning with ver-
sion 1.1), and automatically appears when the system is started.
Accordingly, Presentation Manager applications, which integrate
smoothly with this default environment, should be in great demand.
Unfortunately, however, developing an application for the Presenta-
tion Manager is not a trivial task for the programmer accustomed to
traditional programming environments. There are two basic reasons for
the initial difficulty in writing a Presentation Manager program. First,
as you will see in this book, the basic architecture of a Presentation
Manager application is radically different from that of a traditional pro-
gram. Second, the Presentation Manager is designed to provide a
sophisticated interface for a wide variety of graphics and text mode
programs. Accordingly, the number of function calls it provides is vast,
and many of these function calls accept a large and complex set of
parameters and options. As you develop Presentation Manager applica-
tions, you will likely come to appreciate the variety and subtlety of con-
trol afforded by the Presentation Manager application program
interface. Initially, however, the complexity can form an obstacle to
learning and using the system.
This book is written to help you overcome both of these difficulties.
First, Part I of the book gently introduces you to the basic program ar-
chitecture by tracing the development of a typical Presentation
xix.

Manager application-a text editor-beginning with a simple program


shell and then gradually, chapter by chapter, adding features to this
basic structure until it becomes a complete and useful application.
Second, rather than presenting a large collection of functions at once,
the book introduces the Presentation Manager services individually,
and only as they are required in the development of the example pro-
gram or in the treatment of the current topic. Thus, the description of
the program interface unfolds gradually, and each function is explained
within a context that clarifies its purpose. Also, unlike the technical
documentation, this book does not have the burden of presenting ¢JJ the
features of each function; accordingly, the explanations of the functions
focus on the essential elements and omit some of the confusing details
that are important only for more advanced applications.
The book is written to be a first learning resource as you approach the
Presentation Manager. It is designed to facilitate the initial learning
pi-ocess so that you can begin to enjoy the benefits of programming
under this environment as quickly as possible.

BACKGROUND
• AND REQUIREDTOOLS
Given the ambitious scope of the book, there is little opportunity
to explain programming basics. To understand the coding techniques
and the example program listings, you should have a basic familiarity
with the C language (the Bibliography recommends several books that
will help you improve your C programming skills). Fortunately, the
book uses no assembly language.
Because all Presentation Manager applications run in the protected
mode of OS/2, it would also help to have an understanding of the basic
architecture of the Intel 80286 processor and the features of the OS/2
operating-system kernel. The first chapter briefly summarizes the un-
derlying facilities of OS/2; for additional information, see the
Progr¢777777cr's G#z.dc fo OS/2 or one of the other books on OS/2 kernel
programming cited in the Bibliography.
Programmers who have written applications for Microsoft Windows
will find many features of the Presentation Manager quite familiar.
•XX

However, a background in Windows programming is 7iof rcq#z.red to


fully understand the techniques presented in this book.
To prepare the example programs given in this book, and to write
your own applications, you will need a programmer's toolkit designed
specifically for developing Presentation Manager applications. The ex-
ample programs were developed using the Microsoft OS/2 Software
Development Kit, which includes the operating system and many
programming tools. The following toolkit components were used to
develop the programs in the book: the C compiler (version 5.1), the
OS/2 header and library files, the Dialog Box Editor, the Icon Editor,
the resource compiler, the MAKE utility, the linker, and the online help
facility (QuickHelp).

• OVERVIEWOFTHE BOOK
This book is divided into two parts. Part I describes the essential
elements of a Presentation Manager application and provides the step-
by-step techniques for writing a basic program. Part 11 explores a set of
more advanced topics.
Part I consists of Chapters 1, through 8. Chapter 1 summarizes the
underlying facilities of OS/2 and the general features of the Presenta-
tion Manager; the purpose of this chapter is to provide an overview of
the context in which Presentation Manager applications run. The
remaining chapters in Part I describe the specific techniques for
developing a basic Presentation Manager application. These chapters
are based upon a single example program: a Presentation Manager text
editor.
Chapter 2 describes how to write the basic program skeleton, which
displays a window on the screen and writes a single line of text to this
window. Although this program performs only a rudimentary set of
tasks, it contains most of the essential elements of a Presentation
Manager application.
Chapter 3 then shows how to use the Presentation Manager memory-
management functions to provide a buffer for storing the file data man-
aged by the text editor. This chapter also describes how to display
multiple lines of text within the window, how to handle errors that occur
when calling Presentation Manager functions, and how to use the
xxi.

Presentation Manager macros. The version of the example program


presented in this chapter reads a text file and displays as many lines
from the beginning of the file as will fit in the current program window.
Chapter 4 illustrates the techniques for adding horizontal and verti-
cal scroll bars to the program window, and for scrolling the window
data as the user operates the scroll bars with the mouse. This chapter
also explains how to provide a simple keyboard interface that reads the
arrow keys and allows the user to scroll the file data without a mouse.
The resulting version of the example program permits the user to read a
text file and view any portion of this file within the window.
Chapter 5 shows you how to manage a Presentation Manager cursor,
which marks the current insertion point within the file. This chapter ex-
plains how to create and display a cursor, and how to move it in
response to keyboard commands.
Chapter 6 explains how to implement a full keyboard interface,
which processes normal character keys, as well as function keys, arrow
keys, and other control keystrokes. This chapter also presents a set of
routines for inserting and deleting data from the text file. The version
of the example program given in Chapter 6 provides a full set of com-
mainds for adding and modifying file data.
tchapter 7 describes the techniques for designing and installing
Presentation Manager menus, which allow the user to select and ex-
ecute program commands. This chapter also explains how to define ac-
celerator keys, which are keystrokes that directly activate commands,
bypassing the program menus. In addition, Chapter 7 presents the
routines for implementing several of the menu commands.
Chapter 8 describes the methods for designing, displaying, and
managing dialog boxes. Dialog boxes are temporary windows used to
display information and obtain data from the user. Dialog boxes are
typically displayed when the user selects a menu item that requires ad-
ditional information. This chapter also presents the final complete list-
ing of the example program, which implements most of the essential
features of a text editor.
Part Two (Chapters 9 to 12) explores several advanced features of the
Presentation Manager that can be used to enhance the applications you
write. Chapter 9 describes how to write an interface to the Presentation
Manager clipboard, which is a facility for transferring data within a
single program or among separate applications. This chapter shows
• xxii

you how to use the clipboard to implement cut, copy, and paste com-
mands within the text editor presented in Part I.
Chapter 10 covers the techniques for defining and using several
types of Presentation Manager resources, including icons, pointers, bit-
maps, strings, and programmer-defined resource types. By using
resources, you can define graphic or textual data, store the data within
special segments in the program file, and then load and use the data
when required at run-time.
Chapter 11 explains how to add a mouse interface to your applica-
tion. Specifically, it shows how to read the position of the mouse
pointer, how to control the shape of the pointer, and how to detect the
state of the mouse buttons. The examples in this chapter also
demonstrate several of the Presentation Manager graphics functions.
Finally, Chapter 12 shows you how to improve the efficiency and
responsiveness of your Presentation Manager applications by using
multiple threads of execution. This chapter also explores the methods
for smoothly synchronizing the activities of separate program threads.
As an example, the chapter shows you how to implement a print
routine as a secondary thread within the text editor presented in Part I.
The appendices provide reference material that will be useful both
while you read the book, and when you begin developing Presentation
Manager applications. Appendix A contains a glossary that defines
many of the terms you will encounter while working with OS/2 and the
Presentation Manager. Appendix 8 briefly summarizes each of the
operating-system services discussed in the text, and Appendix C
provides the same information for the predefined Presentation
Manager messages. The Bibliography lists books that are useful for ob-
taining background information or for exploring specific topics in
greater depth. Finally, the inside covers of the book provide a list of the
system functions and messages discussed in the text, organized accord-
ing to the types of services they perform.

• HOWTOUSETHEBOOK
Although the book contains a large amount of reference material,
it is primarily tutorial. Ideally, you should start by reading all of the
xxiii .

chapters in Part I in order; each of these chapters builds upon the con-
cepts presented in the previous chapter. If desired, you can then read
selected chapters in Part 11. Each of these chapters relies upon the
material of Part I, but does not necessarily depend upon the previous
chapter.
Note that each chapter has a primary topic indicated by its title, but
also presents many subsidiary topics. In general, topics are explored as
they are first encountered in the development of the example programs.
Accordingly, the discussions in this book are presented in approximate-
ly the same order in which you would normally encounter them when
developing a Presentation Manager application.
The book contains basic reference information covering a large set of
the Presentation Manager functions and predefined messages. Once
you have read the book, you will find this reference material useful for
developing your own applications. Each of the functions or messages
discussed in the text is described in an accompanying figure. You can
locate the appropriate figure in one of two ways. First, if you are search-
ing for a suitable function or message, you will find each of them listed
on one of the inside covers of the book according to the type of service
it provides, including a reference to the corresponding figure. Second, if
you already know the name of the desired function or message, you can
find a brief description and a figure reference in Appendix 8 (the func-
tions) or Appendix C (the messages).
The Presentation Manager documentation contains a large number
off newly coined words and expressions, as well as common terms that
have specific, nonconventional meanings. If a term is unfamiliar, or if
you are uncertain of its meaning in a specific context, be sure to look it
up in the glossary (Appendix A).
Although the book does not supply formal programming exercises,
many of the chapters have a section near the end that describes possible
enhancements to the example code presented in that chapter; you can in-
plement selected enhancements as exercises in Presentation Manager
programming. Also, the chapters in Part 11 describe the general procedures
for adding features to the example program given in Part I; you can imple-
ment these procedures as additional programming exercises. Finauy, the
book may inspire you to explore advanced Presentation Manager features
that could not be included, and to add these features to the example
programs or to use them in developing your own apphcations.
• xxiv

COMPANION DISKETTE SET


• AND PROGRAMMER'S TOOLS
You can obtain a set of companion diskettes directly from the
author. The two diskettes provide all program listings given in this
book, plus all additional files needed to prepare the example programs.
You can also order a full-featured version of the text editor presented
in the book, which will allow you to write programs and other text files
within a Presentation Manager window. This program provides an on-
line help facility; cut, paste, and other block operations; search and
replace commands; background compiling; macros; and many other
features.
Additionally, you can order a set of software tools for writing OS/2
kernel and Presentation Manager applications. This tool set includes a
useful collection of dynamic-link library functions, plus a set of
programmer's utilities. Complete source code is provided for all func-
tions and utilities.
See the diskette offer in the back of the book for more information
and for details on ordering these items.
PART

BASIC:
FEAT`urREs
ost of this book is devoted to detailed, step-by-step pro-
cedures for developing OS/2 Presentation Manager ap-

.tw plications. The purpose of the first chapter, however, is


to provide you with an overview of the general features
of OS/2 and the Presentation Manager before you become immersed in
the programming specifics given in the remainder of the book.
The first section of this chapter summarizes the basic features of
OS/2 that support all types of programs running under the system, in-
cluding the Presentation Manager. The second section then introduces
the general facilities of the Presentation Manager that support the spe-
cial applications that are the topic of this book. Once you have read this
chapter, you will have a good understanding of the general context in
which Presentation Manager applications run, and you will be ready to
begin leaming the specific guidelines for developing these programs.

• OS/2FEATURES
As mentioned in the Introduction, the Presentation Manager is an
operating-system cxfc77s€.o71. It is implemented through the basic
facilities of the OS/2 kernel that support all types of OS/2 programs.
This section describes these basic features and explains how they relate
to the Presentation Manager and the applications written for it. For an
in-depth treatment of the OS/2 kernel and application program inter-
face, refer to the Progr¢777777cr's G#z.dc fo OS/2 or one of the other books on
OS/2 kernel programming cited in the Bibliography.

Screen Groups
One of the primary features of OS/2 that distinguishes it from
MS-DOS is the existence of multiple sc7'cc71 971o#z7s (also known as scs-
sz.o77s). Each screen group consists of one or more programs that share
the screen, keyboard, and mouse. You can run as many as 14 simul-
taneous screen groups, but you can view and interact with only one of
them at a time (which is known as the /oregro%71d screen group). The
screen groups relegated to the background continue to run concurrently
(except for the real mode screen group, described later in this section).
• 4 Programmer's Guide to the os/2PresentationManager

However, background screen groups no longer write to the physical


screen or receive input from the actual keyboard or mouse; rather,
screen output and keyboard or mouse input are temporarily stored in
internal buffers known as virtual devices. You can switch among screen
groups, bringing one at a time to the foreground, by pressing the Alt-
Esc system hotkey, or by using the session manager, described later in
this chapter.
It is generally safest to run each application in a separate screen
group so that its console I/0 does not conflict with that of other
programs. Thus, you can run several unrelated programs concurrently
but can normally view only one of them at a time. However, if the
Presentation Manager is installed, you can run multiple applications
within a s€.7igJe scrcc71 97'ot/p; within this screen group, you can view
several programs simultaneously within windows on the screen. This
arrangement is possible because the Presentation Manager channels all
console I/0 to the appropriate window, and Presentation Manager ap-
plications are written to cooperate with other programs that share a
common screen, keyboard, and mouse. (Note, however, that not all
programs can run within a window of the Presentation Manager; some
applications must run within separate screen groups. See the section on
Types of Programs Managed by the Presentation Manager, later in the
chapter.)
There are two basic types of screen groups under OS/2. First, there
can be a single 7`c¢J-77zodc screen group. Programs in this environment
run in the real mode of the 80286 or 80386 processor, which emulates the
operation of the 8086 and 8088 processors and therefore supports stand-
ard MS-DOS applications. Accordingly, the real mode screen group is
also called the DOS co777p¢fz.bz73.fy Z7ox, and it allows you to run MS-DOS
software in addition to running applications written specifically for
OS/2 in other screen groups. Note, however, that real mode applica-
tions are suspended when this screen group is placed in the back-
ground. The real mode screen group runs a copy of the
COMMAND.COM command interpreter, and thus presents the same
user interface as MS-DOS.
Second, there are one or more profecfed 77iodc screen groups. Programs
in these screen groups run in the protected mode of the 80286 or 80386
processor (therefore, OS/2 reqt".res the 80286 or later model processor).
The protected mode provides hardware support for multitasking,
Orientation 5 .

alELows programs to access a large virtual address space, and prevents


individual programs from sabotaging other applications or the operat-
ing system. Programs written for the protected mode use the same basic
instruction set as real mode applications; however, they must obey cer-
tain rules, and under OS/2 they require a special .EXE file header.
Therefore, you need to use a compiler and linker designed specifically
to generate protected mode programs. The features of OS/2 discussed
in the remainder of this section apply only to protected mode screen
groups. Note that you can run a copy of the protected mode command
interpreter (CMD.EXE) in any protected mode screen group, which can
be used to execute commands or load and run programs in a manner
similar to MS-DOS.
The Presentation Manager and the applications it manages run
within a protected mode screen group; these programs therefore benefit
from all the features of the protected mode, and must abide by the
guidelines for writing protected mode programs. The Presentation
Manager provides an alternative to the standard command-line inter-
face. Note that it is possible to simultaneously run a collection of ap-
plications within the Presentation Manager screen group, several
protected mode programs within other screen groups, ¢71d an MS-DOS
application in the DOS compatibility box.
Running multiple screen groups requires a scssz.o# 772¢7i¢gcr to help
you start new screen groups or switch to screen groups that are already
running. Under OS/2 version 1.0 (which does not include the Presenta-
tion Manager), the session manager is a text-mode shell program that
occupies its own screen group; you can activate this program using the
Ctrl-Esc system hotkey. In versions of OS/2 that include the Presenta-
tion Manager (1.1 and later), the text-mode session manager is replaced
by a graphical User Interface Shell that runs under the Presentation
Manager, and therefore appears within windows in the Presenta-
tion Manager screen group (the elements of this shell are described later
in the chapter).
Figure 1.1 illustrates the multiple screen groups in a version of OS/2
that includes the Presentation Manager and that is con figured to con-
tain a DOS compatibility box. See the section on Types of Programs
Managed by the Presentation Manager, later in the chapter, for an ex-
planation of the types of applications that can run in each of these
screen groups.
• 6 Programmer's Guide to the os/2 Presentation Manager

Protected Mode
Screen Group
(OS/2 Kernel APplication) A|t-Esc
Alt-Esc/
\s`w:::hEsi \ Pressecnrtea:I:nGyo:npager
Ctrl-EscSwitch PM User PM AppInterfaceKernelAppShellpMApp
Peal Mode Screen Group(MS-DOSApplication)

Ctrl-Esc -grjrswitch
\Alt-Esc /Alt-Esc
Protected Mode
Screen Group
(OS/2 Kernel Application)

• Figure 1.1..
OS|2 screen groups

Multitasking
and Interprocess Communication
OS/2 supports multitasking at three distinct levels. Running mul-
tiple concurrent screen groups, discussed in the previous section, repre-
sents the highest level. As the next level of multitasking, OS/2 provides
facilities for executing several programs simultaneously within a single
protected mode screen group. The Presentation Manager uses these
facilities to run multiple applications within windows on the screen.
Also, a given Presentation Manager application can execute other
programs as concurrent child processes. For example, the text editor
presented in this book could execute a compiler as a child process and
continue providing editing functions while the compiler runs. See
Chapter 12 for more information on managing multiple processes.
The lowest level of multitasking under OS/2 is its support for multi-
ple threads of execution within a single program. It is possible to ex-
ecute several sections of the same program simultaneously. Using
Orientation 7 .

multiple threads is an important technique in writing Presentation


Manager applications, and is discussed in Chapter 12.
OS/2 also provides a large set of functions for interprocess com-
munication, which allow the various tasks in the system to exchange
data and synchronize their activities. Chapter 12 explains the use of
semaphores within a Presentation Manager application for synchro-
nizing the actions of several threads of execution.

Virtual Memory
Under the real mode of Intel processors, a memory address con-
sists of a 16-bit physical segment address and a 16-bit offset within that
segment. In the protected mode, however, the physical segment ad-
dress is replaced with a 16-bit scJccfo7`. The selector is not a physical
address, but rather is an index into a table in memory known as a
dcscrz.pfor £¢Z7Jc; the index points to an entry in this table termed a scg-
77zc7tf dcscr{.pfor. The segment descriptor contains the actual physical
memory address of the segment, as well as other information regarding
the segment. Note that under OS/2, memory segments have variable
lengths, with a maximum length of 64 kilobytes. See Figures 1.2 and 1.3
for a comparison of the addressing mechanisms used in real and
protected modes.
The use of selectors and segment descriptors in the protected mode of-
fers many advantages. First, the operating system can allocate memory
to application programs in excess of the amount of physical memory in-
stalled in the machine. Segments that do not fit into physical memory
can be temporarily stored on disk; the segment descriptor contains a bit
indicating whether the segment is currently present in memory or has
been swapped to the disk. This larger-than-life address space is known
as virtual memory. Virtual memory not only allows protected mode ap-
plications to contain considerably more code and data than would be
possible under the real mode, but also simplifies programming. A pro-
gram directly accesses all segments that have been allocated to it as if
they were entirely present in memory; the processor and operating sys-
tem invisibly handle all the details of swapping and rearranging mem-
ory segments.
For example, an application such as the text editor developed in this
book can read an entire large file directly into memory; if the file size
• 8 Programmer's Guide to the os/2 PresentationManager

exceeds the amount of free memory, the operating system will automat-
ically store the excess data on disk and retrieve it when the program a`d-
dresses it. A similar application under MS-DOS would typically have to
read only a portion of the file at a time, and explicitly maintain a set of
temporary disk files to store modified data.
A second advantage of the virtual memory addressing scheme is that
it allows the system to differentiate code and data segments (the seg-
ment descriptor contains a bit indicating whether the associated
segment is executable). The operating system does not normally allow a
program to modify a code segment; since a program cannot corrupt its
own code, several instances of the same program that are loaded into
memory can safely sfe¢re the same code segment, resulting in an efficient
use of memory. (In contrast, data segments either can be private for each
instance of a program, or can be shared by several instances.)

• Figure 1.2..
The real mode addressing scheme
Orientation 9 .

The ability to share code segments has an important implication for


Pi-esentation Manager applications such as the text editor developed in
this book. A useful editor should auow you to open several ffles and
view them simultaneously in separate windows on the screen. Under the
Presentation Manager, you can efficiently run separate instances of
the program in distinct windows, each instance managing a different
file. The program logic, therefore, does not have to deal with multiple
ffles, buffers, and viewing windows. Also, the clipboard facility dis-
cussed in Chapter 9 allows you to copy data from one window to
another as easily as if the windows were managed by the same program.
A third advantage of the virtual addressing mode is that it allows the
system to prevent one application from corrupting another program or
the operating system itself. The virtual memory mechanism contributes

• Figure 1.3..
The protected mode addressing scheme
• 10 Programmer's Guide to the os/2 PresentationManager

to a high level of protection in several ways. First, the descriptors for


segments that are private to a given process are contained in a Joc¢J
dcscr£.pfor £¢Z7Zc that can be accessed only by that process or by the
operating system; thus, a process cannot normally access segments that
it does not own. (Note that there is also a single gJob¢Z dcscrz.pfor £¢bzc that
can be used by any process to access segments shared by the entire sys-
tem. Under OS/2, these segments are employed for such purposes as
storing system-wide information; however, the segments are marked so
that application programs can read but not modify them. Note also that
OS/2 allows two or more processes to sJt¢7ic a specially designated seg-
ment by placing descriptors pointing to this segment within the local
descriptor tables of each process.)
The system also enforces protection by recording the length of each
segment in the descriptor table. If a program attempts to address
beyond the end of a segment it owns, a profccfz.off /##Jf results, which is a
processor event that causes branching to an operating-system error-
handling routine. OS/2 displays a message, terminates the offending
program, and allows other programs to continue running unharmed.
For example, when developing a Presentation Manager program you
will generally encounter a protection fault if you address beyond the
end of an array or use an uninitialized pointer. Although protection
faults may be disconcerting, experiencing them is vastly superior to
having to reboot the computer under a nonprotected operating system
such as MS-DOS.
Finally, the operating system protects itself by assigning each process
a low pr{.t#.Jegc Jez7eJ. Under the 80286/386 processor, processes run at
one of four distinct privilege levels. The OS/2 kemel operates at the
highest level, and generally assigns application programs the lowest
level.Theprivilegelevelofeachcodesegmentisrecordedtogetherwith
the other segment information in the descriptor table. As a result of
their low privilege level, application programs are prevented from ac-
cessing the code and data belonging to the operating system, and are
restricted from using certain machine instructions that could affect the
entire system.
As a consequence of the memory protection mechanisms, a Presenta-
tion Manager application can access only those segments that the
operating system has explicitly allocated for it. The loader allocates
Orientation 11 .

memory for the program's code and data segments at load-time; once
the program begins running, you can dynamically allocate and release
adlditional segments by calling the appropriate Presentation Manager
or OS/2 services. Chapter 3 explains how to use Presentation Manager
functions to allocate and manage dynamic memory.

Dynamic Linking
In addition to the standard linking mechanism used by MS-DOS,
OS/2 supports a radically new process known as dy71¢77zz.c Jz.77kt.77g.
Under the standard linking method, the linker must bind the target
code for all call instructions directly into the executable file. Figure 1.4
illustrates the standard linking procedure for an MS-DOS or OS/2 pro-
gram that calls routines belonging to a conventional function library.
The linker physically combines the program object code (contained in
an .OBJ file) with the object code for any library modules that are called
(contained in .LIB files), producing a sz.7tgJc executable file on the disk.
When the program is run, this entire file is loaded into memory,
generating a single executable image containing both program and
function library code.
In contrast, Figure 1.5 illustrates the dynamic linking procedure for
an OS/2 protected mode application that calls external functions
belonging to a dy7t¢77#'cJz.77k Jz.Z7r¢7ry. The primary distinguishing feature
of the dynamic linking mechanism is that the external function code is
77of bound into the executable (.EXE) file, but rather is stored in a
dynamic-link library file (with a .DLL extension), which is kept on the
user's disk and is read into memory when the program is loaded. In
other words, binding of code is delayed from link-time to load-time.
In the same manner as the standard linking mechanism, the linker
processes both an object file (.OBJ) and a library file (.LIB). Although the
library file used for dynamic linking is given the usual .LIB extension, it
is a special file known as an z'77zporf Jz.I"#7t/. An import library does 71o£
contain the actual function code; rather, for each dynamic-link function,
it contains a dc/z.7iz.£z.o# record that gives the name of the dynamic-link
library file that contains the function, and the entry point of the func-
tion within this library. This information is stored in the .EXE ffle header
in rcJocofz.o7i records that are used when the program is loaded. Thus, ex-
ternal function references are resolved not by binding in actual code,
• 12 Programmer's Guide to the os/2Presentation Manager

but by writing a record for each function that tells the loader how to
resolve the references to the function when the program is run.
When the program is run, the loader first reads the program code
into memory; it then loads all referenced dynamic-link library files that

• Figure 1.4..
The standard linking mechanism
Orientation 13 .

have not already been loaded. Finally, it ``fixes up" all references within
the program code to dynamic-link functions by supplying the actual far
address (that is, selector and offset) of the function in memory. Thus,
calls to dynamic-link functions become direct intersegment calls to the
entry points of the functions in memory.
An important feature of dynamic-link libraries not indicated in Fig-
ure 1.5 is that several concurrent applications can sfe¢7ie a single

• Figure 1.5..
The dynamic linking mechanism
• 14 Programmer's Guide to the os/2 Presentation Manager

dynamic-link library module that has been loaded into memory.


A dynamic-link module is loaded when it is first referenced by an ap-
plication program (a cJ€.c77£). When subsequent applications reference
this same library, the loader does 77of read in additional copies but rather
allows the applications to share the library code segments that have al-
ready been loaded. When the last client terminates (that is, when the rc/-
cre7ice cot47if goes to 0), the dynamic-link library is freed from memory.
Note that a dynamic-link library module has an opportunity to perform
initializations either when it is first loaded into memory or whenever
the module is first referenced by subsequent client programs.
In addition to the advantage of being able to share dynamic-link
library code among multiple applications and thereby reduce memory
requirements, dynamic linking offers several other advantages over the
standard linking mechanism. First, with the standard linking method, a
separate copy of the library code must be stored in each .EXE file on
disk. With dynamic linking, however, each .EXE file stores only the
names and entry points of the functions; only a single copy of the code
is stored on disk (in a .DLL file), and therefore disk space is saved.
Second, if the code in a standard library file is modified, all applica-
tions that use the library must be recompiled (and possibly
redistributed to the users); changes can be made to dynamic-link
libraries, however, that will globally affect the behavior of all calling
programs without the need to recompile these programs.
Finally, although loading the first application that references a
dynamic-link library is slower than loading a traditionally linked pro-
gram (since separate files must be read rather than a single executable
image), loading all subsequent applications that use the same library is
faster, because the .EXE files are smaller and the library code is already
in memory.
The dynamic linking mechanism is important for Presentation
Manager applications for several reasons. First, the OS/2 application
program interface (API) is implemented as a set of dynamic-link library
modules. The OS/2 API is the basic set of operating-system services
that support all types of programs in the system; many of these func-
tions are used by the Presentation Manager and can be called by Presen-
tation Manager applications. The OS/2 API services have the prefixes
Dos, Vz.o, Kbd, and Mot4, and they are briefly described in the next sec-
tion. In this book, these functions are classified as the OS/2 APT and are
Orientation 15 .

distinguished from the Prcsc71£flfz.o7i M¢71¢gcr APT functions discussed in


the last section of the chapter.
Because the operating-system services are supplied as dynamic-link
libraries, accessing them from high-level languages is very efficient;
rather than requiring an indirect interface function such as intdos in the
C library, invocations to operating-system services are simple direct
calls to the OS/2 code in memory, and they use the standard high-level
language function-calling syntax. For example, the fouowing C state-
ment generates a direct call to the OS/2 service that obtains the current
disk drive:

DosQCurDisk (&DriveNumber, &LogicalDriveMap) ,.

The code for the OS/2 API services is contained in a variety of dynamic-
link libraries, such as DOSCALL1.DLL and VIOCALLS.DLL.
A second reason for the importance of the dynamic linking
mechanism is that the Presentation Manager itself is implemented as a
collection of dynamic-link modules. A Presentation Manager applica-
tion is one that calls dynamic-link functions belonging to the Presenta-
tion Manager API. As you begin developing a Presentation Manager
application, you will notice that although the program calls a large
number of Presentation Manager functions, the .EXE file remains quite
small. The small size is due to the fact that the executable file does 77of
contain the actual Presentation Manager function code, but only
dynamic-link records in the .EXE header. The actual function code is
stored in dynamic-link libraries with names such as PMWIN.DLL on
your disk and on the disk of the ultimate user of the program. When the
first Presentation Manager application is run (normally the User Inter-
face Shell), the loading process is quite lengthy, since a great amount of
dynamic-link code must be loaded and initialized. Subsequent Presen-
tation Manager applications, however, load quickly and use the
dynamic-link code already present in memory.
Note that although the Presentation Manager is an extension added
to the original version of OS/2, the protocol for calling its functions is
identical to that of the basic OS/2 API. Such seamless extensions to the
operating system are made possible through the dynamic linking
mechanism. A final reason for the importance of dynamic linking is that
any software developer can provide custom extensions to the operating
system (or to the Presentation Manager in particular) by writing a set of
• 16 Programmer's Guide to the os/2 Presentation Manager

functions and packaging them as a dynamic-link module. These func-


tions can be called in the same manner as the OS/2 and Presentation
Manager API services, can be accessed from any programming lan-
guage, and can be sfe¢rcd by all running programs. (OS/Tools for the
Presentation Manager, described in the diskette offer at the end of the
book, is an example of such a package. See Chapter 10 of the
Progr¢7777„cr's Gt#.de fo OS/2 for instructions on developing your own
dynamic-link libraries. )

The OS/2
Application Program Interface
As mentioned in the previous section, the services of the OS/2 ap-
plication program interface (API) are implemented as dynamic-link
libraries and can be called directly by OS/2 kcr7icJ progr#77ts (that is, non-
Presentation Manager applications); many of these functions can also
be called by Presentation Manager applications. The OS/2 API func-
tions fall into four basic categories; the first three letters of the function
name indicate the general category of the function. For example, Vio-
Wrtcharstr belongs to the set of video functions. The following are the
four groups of OS/2 API functions:

Prefix Purpose of Functions


Dos General-purpose system functions
KZ7d Keyboard-management functions
Mow Mouse functions
Vz.o Screen-management functions

The general-purpose Dos functions provide a wide variety of ser-


vices. These functions can be divided into the following general clas-
sifications according to the type of services they provide:

• Program startup information


• Memorymanagement
• Disk file and character device I/O
Orientation 17 .

• Disk, directory, and file management


• Low-level device control
• Managementof threads
• Managementof processes
• Managementofscreen groups
• Interprocess communication
• Timeanddatemanagement
• National lan.guage support
• Run-time dynamic linking
• Device monitor management
• Errorhandling
• Additional functions

Most of the Dos functions can be called by Presentation Manager ap-


plications; these functions provide many services not offered by the
Presentation Manager API. Some of the Dos functions, however, may be
incompatible with the Presentation Manager environment, such as
those for low-level device control and device monitor management.
Also, a Presentation Manager application cannot use the function Dos-
WIfite to generate screen output. Note that many C library functions,
sutch as fopen and read, ultimately call OS/2 Dos services.
The KZ7d, Mow, and Vz.o functions provide a comprehensive set of ser-
vices for managing specific devices. Presentation Manager applications,
however, should 77of call any of the KZ7d or MotJ services; rather, they
should use the special Presentation Manager API services and messages
(explained in Chapter 2). Note that certain Presentation Manager ap-
plications (those that use the ¢dz7¢77ccd Vfo functions mentioned at the
end of the chapter) can use a large subset of the OS/2 Vt.o functions; the
programs discussed in this book, however, co7z7tof call OS/2 Vz.o func-
tions (advanced Vz.o applications are beyond the scope of this book).
When writing a Presentation Manager application, it may be possible
to obtain a given service through the Presentation Manager API, either
through the Dos functions of the OS/2 API, or through the C library. For
example, you can dynamically allocate blocks of memory using the
• 18 Programmer's Guide to the os/2 PresentationManager

Presentation Manager heap-management functions (described in Chap-


ter 3), through OS/2 API services, or by means of C library functions.
The programs in this book use Presentation Manager functions when-
ever possible (because these functions are the topic of the book), and C
library functions for services not provided by the Presentation Manager
(because these functions are familiar to C programmers). In certain
cases, however, it might be more efficient to call OS/2 API functions
directly.
Note that if you call functions belonging to the OS/2 API, you must
specify the appropriate import library when linking the application.
This library is named DOSCALLS.LIB in version 1.0 of OS/2, and
OS2.LIB in version 1.1; consult your documentation for the correct
name. To learn more about the OS/2 API functions, see the OS/2
Progranmer's Tloolkit Progranmer's Reference or the Programmer's Guide
to OS12.

PRESENTATION
• MANAGERFEATURES
This section provides a brief overview of some of the general fea-
tures of the Presentation Manager to help you gain an understanding
of the context in which Presentation Manager applications run. Most of
the features of the Presentation Manager are explored in subsequent
chapters when they are first encountered while developing the example
application that forms the heart of the book. This section covers the fol-
lowing introductory topics:

• The user Interface shell


• The types of programs managed by the presentation Manager
• ThepresentationManagerAPI

The User Interface Shell


When a version of OS/2 including the Presentation Manager is
started, the User Interface Shell is normally the first application to begin
Orientation 19 .

running (provided that this shell is specified with the PROTSHELL


command in the configuration file). The User Interface Shell consists of
a collection of Presentation Manager applications that run within win-
dows in the Presentation Manager screen group. This shell replaces the
text-mode session manager used in OS/2 version 1.0; it also replaces
the standard command-line interface of the protected mode command
interpreter (CMD.EXE). Once the shell is running, you can use it to load
and run other applications (Presentation Manager as well as kernel
programs), to switch to applications that are already running, to
manage files and directories, and to set Presentation Manager system
parameters. Presentation Manager applications run within windows of
various sizes, which are normally arranged in an overlapping fashion
(this arrangement is picturesquely described as c¢sc¢dcd; you can op-
tionally have the Presentation Manager position windows in a fl7cd, or
side-by-side, arrangement).
The following are the basic components of the User Interface Shell
that are briefly described in this section (note that these components
may vary with different versions and releases of the operating system):

• TheTaskManagerwindow
• Theprogramstarterwindow
• The presentation Manager control panel
• The presentation Manager Filing system

The Task Manager Window


You can activate the Task Manager window from any other pro-
gram in the system by pressing the Ctrl-Esc key combination. This win-
dow displays a list of currently running applications; you can
immediately activate any of these programs by selecting it from this list.
You can also terminate a running application directly from the Task
Manager window, without first activating the program and stopping it
through the normal program commands. In addition, the Task Manager
allows you to save a list of programs and the data files these programs
use, so that the specified configuration of programs and data files will
automatically be established when the system is restarted. Finally, the
• 20 Programmer's Guide to the os/2 PresentationManager

Task Manager allows you to shut down the system in preparation for
turning off the machine; this procedure automatically terminates all
running programs.
Note that the Task Manager handles not only applications running
within Presentation Manager windows, but also kernel programs in
other screen groups. If you have con figured the system to include the
DOS compatibility box, the DOS command prompt appears in the list
of running programs; you can switch to this screen group and run MS-
DOS applications from the command prompt.

The Program Starter Window


The Program Starter window allows you to start new protected
mode programs. This window displays a list of applications that have
been installed; you can run a program by selecting it from this list. Also,
you can add programs to the list, delete programs, or modify the infor-
mation that is maintained for each program (such as the parameters and
the startup directory). The list of programs is organized into groups,
and you can choose the particular group you would like to view. The
Program Starter window allows you to add, delete, or rename groups.
Note that this window can be used to start applications within the
Presentation Manager screen group as well as kemel programs running
in other protected mode screen groups.
The Program Starter window additionauy anows you to run one or
more copies of the protected mode command interpreter (CMD.EXE) so
that you can start programs in the traditional manner from the OS/2 com-
mand prompt. You can run the command interpreter either within a win-
dow of the Presentation Manager, or in another screen group (in which
case, it will use the entire screen). Note that you can also start programs
from the Presentation Manager Filing System, described below.

The Presentation Manager Control Panel


You can use the Presentation Manager Control Panel to set a wide
variety of parameters that affect the behavior of Presentation Manager
Orientation 21 .

applications. The following are among the operations you can perform
using this utility:

• Setthesystemdateandtime
• Adjusttheblinkrateof thecursor
• Modifythebehaviorof themouse
• Select window colors and border style
• Specify country-specific information
• Manage the printer, serial port, and other devices
• Add new character fonts

The Presentation Manager Filing System


The Presentation Manager Filing System is a windowed environ-
ment that performs most of the directory- and file-management functions
traditionally executed from a command-line prompt. This utility graphi-
cauy displays directories and files in a treelike representation; you can
view various sections of the directory structure of a given disk in one or
more windows, and select directories and files directly from this display.
once one or more directories or files have been selected, you can perform
any of the normal operations on them. For example, you can start a prcr
gram, copy a file, or create a directory. You can perform these operations
through menus and dialog boxes. Additionally, you can execute many
operations by using the mouse directly on the appropriate icon. For ex-
ample, you can double-chick the mouse on an icon representing an ex-
ecutable file in order to run the program; also, you can drag icons with the
mouse to copy or move files from one directory to another.

Types of Programs
Managed by the Presentation Manager
As mentioned in the previous section, the Presentation Manager
User Interface Shell allows you to run or switch to any program in the
• 22 Programmer's Guide to the os/2 Presentation Manager

system. From the perspective of the Presentation Manager, there are


four basic progran\ classifications:

1. MS-DOs applications running in the real mode screen group


2. Protected mode kernel applications that c¢7171of run within a win-
dow of the Presentation Manager
3. Protected mode kernel applications that c¢# run within a
window of the Presentation Manager
4. Presentation Manager applications; that is, programs written
specifically for the Presentation Manager

MS-DOS Applications
MS-DOS applications can be run only if you have installed the real
mode screen group (using the PROTECTONLY=NO configuration
command). You can start these applications by selecting the DOS com-
mand prompt from the Task Manager and running the programs from
the command line. MS-DOS programs are suspended when you switch
away from the real mode screen group.

Kernel Applications
That Cannot Run in a Window
Kcr71cJ applications are those that use the basic OS/2 API services.
These are applications that have 77of been written specifically for the
Presentation Manager and therefore do 7tof call Presentation Manager
API functions. Many kernel applications can run within a window in
the Presentation Manager screen group; the programs in this category,
however, ccz7t7tof run within a window because they perform some ac-
tion that is incompatible with the Presentation Manager environment.
The following are among the actions that would render a kernel pro-
gram incompatible with the Presentation Manager:

• Writing directly to the physical video buffer


• Switchingvideomodes
orientation 23 .

o Altering the video state by calling the os/2 Apl function


Viosetstate
o Directly programming the video controller registers
o Replacing video, keyboard, or mouse functions (through
VioRegister, KbdRegister, or MouRegister)
a Installing a keyboard or mouse monitor

Note that kernel graphics programs need to perform one or more of


these prohibited actions and are therefore excluded from running
within a Presentation Manager window.

Kernel Applications That Can Run in a Window


Text mode kernel applications that perform I/0 through the Vz.o,
Kbd, and Mot/ functions of the OS/2 API, and do not perform any of the
forbidden actions listed in the previous section, can generally run either
within a window of the Presentation Manager or within a separate
screen group. Although programs in this category can be run within a
window that is controlled by the user through a basic set of system
commands, they cannot take advantage of the extensive set of functions
available for programs written specifically for the Presentation
Manager (they cannot, for example, use menus, dialog boxes, or
graphics functions).
Note that some of the Presentation Manager documentation includes
this category of programs under the description ``Presentation Manager
applications." However, in this book (for lack of any other term)
``Presentation Manager application" rc/ers cxcZ#sz.z7czy fo cz fr#c P7icsc7ifcz-

tion Manager program as descrived in the next section.

Presentation Manager Applications


This final category consists of applications that conform to the ex-
acting program architecture specified by the Presentation Manager,
which will be described throughout the remainder of this book. These
programs can-and must-run within a Presentation Manager window
and have full access to the vast array of services and features offered by
the Presentation Manager. As mentioned previously in this chapter,
• 24 Programmer's Guide to the os/2 Presentation Manager

these programs can use many of the Dos functions of the OS/2 API, but
should not call KZ7d or Mot/ services, and only applications that make
proper use of the advanced Vc.o Presentation Manager functions (men-
tioned in the next section) may call OS/2 Vz.o services.

Comments
The text editor developed in this book is, of course, a Presentation
Manager application as defined in this section. Note that applications in
the last three categories (the protected mode programs) should have a
flag in their .EXE file headers indicating to which of these three
categories they belong. This flag enables the Presentation Manager to
handle these programs correctly when they are loaded. The flag, how-
ever, may be absent from protected mode applications prepared with
earlier versions of the linker; such unmarked kernel programs cannot
run within a window (unless they are run through the Program Starter
window and you have explicitly changed the installation information
to indicate that the program can be run in a window). Microsoft, how-
ever, provides a utility (MARKEXE.EXE) that enables you to correctly
mark the .EXE header for these programs.

The Presentation Manager API


The reward for conforming to the exacting architecture specified
by the Presentation Manager is the use of the vast collection of services
belonging to the Presentation Manager API. Only true Presentation
Manager applications, as defined in the previous sections, can call these
functions. An explanation of the Presentation Manager API will unfold
gradually in the subsequent chapters; this section merely lists the
general function categories. Like the OS/2 API described earlier, the
first three letters of a function name indicate its general category. The
following are the groups of Presentation Manager API functions:

Prefix Purpose of Functions


DctJ Functions for managing devices
Gpz. Graphics functions
Orientation 25 .

Print spooler functions


Advanced Vfo functions for displaying character-
based data; applications that use these services may
also call many of the V1.o functions of the OS/2 kernel
(these functions are not discussed in this book)
Win Window-management and general-purpose Presenta-
tion Manager functions

As comprehensive as this set of functions may be, it does not exhaust


the resources available to Presentation Manager applications. Presenta-
tion Manager applications can also obtain a great number of services by
sending messages to window procedures belonging to the system. This
concept will not likely make sense at this point, but will be fully ex-
plained in Chapter 4.

• CONCLUSION
This chapter has provided a brief overview of the context in which
Presentation Manager applications run. It has summarized the general
features of the OS/2 kernel and the Presentation Manager user inter-
face. It has also introduced the Presentation Manager programming in-
tei.face, which will be described in subsequent chapters. The remaining
chapters in this book explore the specifics of creating a Presentation
Manager application.
2:J.

.I
his chapter presents the rudiments of the Presentation
Manager text editor that win slowly evolve, chapter by
chapter, into a complete and useful application. The ver-
sion given here simply displays a window on the screen
and prints a line of text at the top of the window. You win see, however,
that coustmcting even a minimal Presentation Manager application re-
quires writing several procedures and calling quite a number of functions.
This program contains most of the essential elements of a Presenta-
tion Manager application and provides a basic framework for sub-
sequent versions. Even though it seems that the Presentation Manager
exacts a large overhead merely to place a window on the screen, this
window is not a simple inert object. A window cannot be placed on the
screen with other programs unless it has a basic set of capabilities. The
staindard window created in this chapter has components that allow
you to move it on the screen, change its size, minimize or maximize it,
and terminate the program. You can perform these actions either
through a menu or by acting on a set of graphic objects with the mouse.
Furthermore, the window must be able to repaint itself whenever any
of its data are destroyed as the user moves and manipulates the objects
on the screen.
In this chapter, you will learn how an ordinary C program becomes a
Presentation Manager application; you will learn the message-based ar-
chitecture of Presentation Manager programs; and you will learn how
to display data within a window. You will also become familiar with
several important services of the Presentation Manager API, and two
Presentation Manager messages.

BECOMING A PRESENTATION
• MANAGER APPLICATION
When you write a Presentation Manager application in the C lan-
guage, you must include the header file OS2.H, which provides a large
number of vital function declarations, type definitions, and constant
definitions for both the basic OS/2 API and for the Presentation
Manager API. Also furnished is a collection of macros useful for
manipulating the data used by Presentation Manager functions and
• 28 Programmer's Guide to the os/2 PresentationManager

messages (see Table 3.2 in Chapter 3 for a description of these macros).


The header information is actually contained in a collection of include
files, which OS2.H incorporates in your program through a series of
nested #include statements. Since the total quantity of header informa-
tion is quite large, only the most commonly used portions are included
by default (otherwise, the compiler would waste time processing un-
necessary data). See Chapter 3 and Table 3.1 for an explanation of how
you can incorporate additional portions of the header information in
your program by defining specific constants before including OS2.H.
Figure 2.1 lists the function main belonging to `the Presentation
Manager application presented in this chapter (note that the program is
listed in its entirety in Figure 2.27, at the end of the chapter). This func-
tion performs the essential steps required of a Presentation Manager ap-
plication. By performing these steps, a program Z7eco771cs a Presentation
Manager application, with all appertaining rights, privileges, and
honors. Specifically, a program obtains the right to run within the
Presentation Manager screen group, and it gains access to the vast col-
lection of Presentation Manager services. The following is a list of these
essential steps:

1. Initialize the presentation Manager


2. Createamessagequeue
3. Registerawindowclass
4. Create a window
5. Getand dispatchmessages
6. Release presentation Manager resources

Step 1: Initialize
the Presentation Manager
A Presentation Manager application must first call the function
Winlnitialize to initialize the Presentation Manager system for the cur-
rent program and to obtain an ¢7icfeor bzock fe¢7idJc. The anchor block
handle is a value that identifies the application to the Presentation
Creatingawindow 29 .

void main ()
(
HAB HAncBlk; /* Anchor block handle.
HMQ HMesQue; /* Message queue handle.
HWND HFrame, Hclient; /* Frame/client window handles.
QMSG QueMess; /* Message queue structure.
ULONG CtlData = /* Control windows to include.
FCF MINRAX /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
F'CF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
/*** Initialize the Presentation Manager and obtain an anchor block handle. **/
HAncBlk = Winlnitialize /* Returns an anchor block handle. */
(0); /* Initialization options: must be 0. */
/*** Create a message queue for the current thread. **************************/
HMesQue = WincreateMsgQueue /* Returns a message queue handle. */
(HAncBlk, /* Anchor block handle. */
0); /* Minimum queue size: 0 means default size.*/

/*** Register a window procedure. ********************************************/


WinRegisterclass
(HAncBlk, /* Anchor block handle.
„RAIN„ ,
/* Window class name.
Wndproc, /* Window procedure associated with class.
OL, /* Class style: no styles specified.
0); /* Bytes of data storage for each window.
/*** Create a standard window. ***********************************************/

HFrame = Wincreatestdwindow /* Returns handle to frame window.


(HWND DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style.
&cEIData' /* Address of control data.
''MAIN„ ,
/* Client window class name.
'': PM Text Editor", /* Text for title bar.
OL' /* Client window style: none specified.
0, /* Resource module handle: none.
0' /* Resource identification: none.
&Hclient) ; /* Address to receive client window hand.
/*** Main message-handling loop. *********************************************/

while (WinGetMsg /* Get messages until WM_QUIT.


(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure.
0, /* Window filter: any window.
0, /* First message identifier: n/a.
0)) /* Last message identifier: n/a.

• Figure 2.1..
The function "aiin of the exanple program
• 30 Programmer's Guide to the os/2 Presentation Manager

WinDispa tchMsg (HAncBlk, &QueMess) ; /* Dispatch messages. */


*/
/*** Relinquish Presentation Manager resources and terminate application.
WinDestroywindow (HFrame) ; /* Eliminate the window. */
WinDestroyMsgQueue (HMesQue) ; /* Eliminate the message queue. */
WinTerminate (HAncBlk) ; /* Sever ties with the Presentation */
/* Manager and release resources. */
} /* end main */

• Figure 2.1..
The function rr\a;in of the example program (continued)

Manager; you must save this number and pass it as the first parameter
to several other Presentation Manager functions.
Winlnitialize is described in Figure 2.2. As each new Presentation
Manager function is encountered in the discussions in this book, it is
described in an accompanying figure. Note that these descriptions focus
on the features relevant to the techniques presented in the book, and do
not always include all of the options available for a given function. For
complete details, and for documentation on functions not treated in the
book, consult the OS/2 programming reference cited in the Bibliog-
raphy. Note also that Appendix 8 provides an alphabetical summary of
the functions discussed in this book, and the inside book covers list these
functions according to the types of services they provide.
The function Winlnitialize is declared as follows within one of the
OS/2 header files that is incorporated in your program when you in-
clude OS2.H:

HAB APIENTRY Winlnitialize (USHORT) ,.

The special types HAB, APIENTRY, and USHORT are defined within
the OS/2 header files. HAB is a type identifier for an anchor block
handle; it resolves, through several layers of type definitions, to the
basic C type

void far *
Creatingawindow 31 .

Winlnitialize
Purpose..
Initializes the Presentation Manager system for use by the
current program.

Prototype..
IIAB APIENTRY Winlnitialize
(USHORT fsoptions ) ,. Initialization options; must be NULL.

Return Value ..
An anchor block handle.

Notes..
An application must call this function before it can use the
other services of the Presentation Manager. The anchor block
handle should be saved so that it can be passed to sub-
sequent Presentation Manager functions.

• Figure 2.2..
The Winlr\i+ialire Presentation Manager f unction

APIENTRY is a type identifier for API functions. It is equivalent to the


C type

pascal far
The Presentation Manager API services (as well as all OS/2 API ser-
vices and dynamic-link library functions) are far functions, meaning
that they are located in a separate segment in memory and are called
through an address consisting of both a segment selector and an offset.
These functions are also of type pascal, which implies the following
conventions:

• Parameters are pushed on the stack in the s¢777c order that they
are listed in the parameter list (by default in C, they are pushed
in the opposz.fc order).
• 32 Programmer's Guide to the os/2 PresentationManager

The function must remove the parameters from the stack before
returning (the default in C is for the calling program to remove
all parameters from the stack).
Each function has a fixed number of parameters (this is a result
of the first two features; a default C function can accept a vari-
able number of parameters).
• The function name is converted to uppercase before being placed
in the object file toy default, Microsoft C preserves the case of
function names and places an underscore at the beginning of the
name).

Finally, the type identifier USHORT is equivalent to the C type

unsigned int

Note that the function main in Figure 2.1 declares the variable HAnc-
Blk using the same type identifier, IIAB, that is used in the function
declaration in the OS/2 header files; this variable stores the anchor
block handle returned by Winlnitialize. It is generally easiest simply to
use the type definitions given in the function declarations and
documentation, without paying attention to the equivalent basic C
types. These definitions are used consistently throughout the header
files and the technical documentation, and within this book. They pro-
vide more information regarding the purpose of the object than the
simple C data types (for example, knowing that a variable is a handle to
an anchor block is more useful than knowing merely that it is a void far
pointer). Also, it is possible that the basic C types could cfe¢7igc if the
Presentation Manager were ported to another computer system (for ex-
ample, USHORT might be defined as an unsigned short); if you have
consistently used the OS/2 type definitions, your program types will
remain valid.
Note that to facilitate using this book in conjunction with the Presen-
tation Manager technical documentation, the function descriptions use
the s¢777c parameter names found in this documentation. These names
begin with a prefix in lowercase letters, which indicates the fypc of the
parameter (the data type, such as pch, which is a far pointer to a charac-
ter, or the general use of the parameter, such as f, which is a flag). Fol-
lowing the prefix is an optional identifier, which begins with an
Creatingawindow 33 .

uppercase letter and identifies the specific instance of the general type.
For example, the parameter pfnwndproc (passed to WinRegisterclass
and listed in Figure 2.4) is a pointer to a function (pfn) that is used
specifically to pass the address of the window procedure (Wndproc).

Step 2: Create a Message Queue


The function main now calls WincreateMsgQueue (Figure 2.3) to
create a 777css¢gc q#ct& A message queue is a data structure that receives

WincreateMsgQueue
Purpose..
Establishes a message queue that receives messages sent to
all windows created by the current thread.

Prototype..
HMQ APIENTRY WincreateMsgQueue
(RAE hab, Anchor block handle obtained by a prior call
to Winlnitialize.
SHORT cmsg) ,. Maximum size of the queue; a value of o
requests the default size.

Return Value ..
A message queue handle, or NULL if unsuccessful.

Notes..
You should call this function after Winlnitialize, but before
calling other Presentation Manager functions. A given
thread can call this function only once.

Related Function..
Winlnitialize (Figure 2.2)

• Figure 2.3..
The Wincreate:MsgQueue Presentation Manager function
• 34 Programmer's Guide to the os/2PresentationManager

and stores messages sent to all windows created by the current program
thread; an application must establish a message queue before it can cre-
ate a window. The program presented in this chapter consists of a single
thread and creates several windows. The system places messages sent
to any of these windows within the queue created by the call to Win-
CreateMsgQueue. As you will see shortly, the system sends messages
to a window to notify it of a wide variety of events; for example, it sends
a specific message when the window needs to redraw a portion of its
data. You will also soon learn how to process these messages. Note that
a value of 0 is passed as the second parameter, which causes the func-
tion to use the default queue size.
WincreateMsgQueue accepts the anchor block handle returned by
Winlnitialize and returns a message queue handle (of type HMQ,
stored in the variable HMesQue). The message queue handle is saved
so that it can later be passed to the function that destroys the message
queue before program termination (WinDestroyMsgQueue). Note that
WincreateMsgQueue, like many Presentation Manager functions,
returns a value of NULL if it is unsuccessful (NULL is defined as 0 in the
C include files STDDEF.H and STDIO.H). The topic of testing for error
return codes, and displaying error messages within message boxes, is
introduced in Chapter 3.
Note that in a multiple-thread application (discussed in Chapter 12),
every thread that creates one or more windows must call Wincreate-
MsgQueue to establish a message queue; furthermore, a given thread
can create only 071c message queue.

Step 3: Register a Window Class


Next, the function main cans WinRegisterclass (Figure 2.4) to create
a window class. Every window created under the Presentation Manager
belongs to a window class that defines a window procedure and other in-
formation (such as default window styles). A window procedure is the
functionthatprocessesmessagessenttoagivenwindow;whenamessage
is extracted from the message queue and dispatched, the system invokes
the window procedure associated with the target window (extracting and
dispatching messages is described under step 5).
Creatingawindow 35 .

WinRegisterclass
Purpose..
Registers a window class.

Prototype..
BOOL APIENTRY WinRegisterclass
(HAB hab, Anchor block handle obtained
from Winlnitialize.
PSZ pszclassName , Pointer to a null-terminated
string containing the class
name to be associated with the
window procedure.
PFNWP pfnwndproc, Address of the window
procedure that is to be
associated with the class name.
ULONG flstyle, The default window style,
which can be one or more of
the class styles (CS_) listed in
Table 2.1; styles specified when
the window is created are
added to the default styles
specified with this parameter.
USHORT cbwindowData) ,. Bytes of storage that should be
reserved for each window
belonging to this class that is
created; this data can be
accessed by functions such as
Winsetwindowushort and
WinQuerywindowushort.

Return Value ..
TRUE if successful, and FALSE if an error occurs.

Related Functions ..
Wincreatestdwindow (Figure 2.5)
Wincreatewindow

• Figure 2.4..
The WinRegisterclass Presentation Manager function
• 36 Programmer'sGuidetotheos/2 Presentation Manager

Asyouwillsee,whenawindowiscreated,itisassignedtoawindow
class; using object-oriented terminology, the window is said to be an I.71-
sf¢7ice of this class. A window can be assigned to a prereg{.sfercd window
class provided by the Presentation Manager for various types of win-
dows; in this case, the system supplies the window procedure that
processes the messages sent to this window. System-supplied window
procedures are located in a Presentation Manager dynamic-link library
and perform minimal default processing in response to messages sent
to the window.
Although the system window procedures associated with pre-
registeredwindowclassesaresuitableformanytypesofwindows,you
should supply your own procedure for the cJ€.c71f ztJ2.#doztL The client
window, as you will see under step 4, is the primary window used for
displaying program data, which is a job that must be performed by
your own window procedure in response to the messages it receives.
Accordingly, you must write a window procedure (Wndproc in the ex-
ample program, listed in Figure 2.16) and call WinRegisterclass to
register a window class that is associated with this procedure (you pass
theaddressoftheprocedureasoneoftheparameters).Asyouwillsoon
see, when you subsequently create the client window, you can make it
an instance of this class; accordingly, all messages sent to this window
will cause your procedure to receive control.
Note that a given window class can have more than one instance; in
other words, several windows can be assigned to a single window class
whentheyarecreated.Consequently,awindowproceduremayhaveto
process messages for multiple windows (the identity of the target win-
dow is supplied as part of the message). However, the window class
created by the example program (which is associated with the window
procedure Wndproc) has only a single instance+the client window.
Atthispointintheprogram,nowindowshaveactuallybeencreated.
WinRegisterclass performs the following three primary functions in
preparation for creating a window:

1. WinRegisterclass creates a window class and assigns this class


an arbitrary name, which is supplied through the second
parameter. The example program chooses the name ``MAIN". As
youwilldiscoverunderstep4,youmustsupplythisnamewhen
creating the client window to make it an instance of this class.
Creatingawindow 37 .

2. WinRegisterclass associates a window procedure with the class


it creates. You specify this procedure by passing its address as
the second parameter; subsequently, the system will invoke the
specified procedure when it sends messages to any window
belonging to this class.
WinRegisterclass assigns a set of default styles (the third
parameter) to the window class. You can specify one or more of

Table 2.1.. Presentation!|]|4g]}ager Class Styles

Class style Effect


CS CLIPCHILDREN The system will exclude the area occupied by the
window's children from the window's cJz.ppz.71g ¢rc¢ (the
area in which it can paint).
CS CLIPSIBLINGS The system will exclude the area occupied by the
window's siblings from the window's clipping area.
CS MOVENOTIFY The system will generate a WM_MOVE message
whenever the window is moved on the screen.
CS PARENTCLIP The system will extend the window's clipping area to
encompass the area of its parent.
CS PUBLIC The system will register a public window class; this style
can be specified only by the shell process.
CS SAVEBITS The system will save the screen area under the window
when it is made visible; when the window is removed,
the system will restore the area it occupied without
sending a WM_PAINT message.
CS SIZEREDRAW The system will invalidate the entire window and
generate a WM_PAINT message (forcing the window
procedure to recreate screen data) whenever the window
is reduced or enlarged in size.
CS SYNCPAINT The system will sc7id a WM_PAINT message directly to
the window procedure whenever any section of the
corresponding window becomes invalid (as opposed to
merely posting the message to the message queue).
• 38 Programmer's Guide to the os/2PresentationManager

the styles listed in Table 2.1. These styles are identified with con-
stants (defined in an OS/2 header file) that have the CS_ (class
style) prefix; if you want more than one style, you must combine
the identifiers with the bitwise OR operator ( I ). The example
program does not require any styles, and therefore passes a
value of 0. If, however, you select one or more styles, all win-
dows subsequently created with this class will automatically ac-
quire the chosen style (in ¢dd£.£1.o71 to any styles specified when
creating the window).

Step 4: Create a Window


The function main is now ready to create a window. A Presenta-
tion Manager window is a highly significant entity; it is not only the
main vehicle for interacting with the program user, but, as you will
soon discover, it is the program object that receives all messages.
The program creates a standard window by invoking the function
Wincreatestdwindow (Figure 2.5). Calling this function is the easiest
way to create a general-purpose main program window that has such
features as a title bar and a system menu. When you call Wincreatestd-
Window, you request the specific features required. Each of these fea-
tures is actually a distinct window (known as co71froJ zul.71dows); thus, the
standard ``window" created by Wincreatestdwindow typically con-
sists not of a single window but of a family of related windows.
The function Wincreatestdwindow creates at least one primary
window known as the fr¢777c window. The frame window has no visible
distinguishing characteristics; however, all of the other windows
created by Wincreatestdwindow, such as the title bar, the sizing bor-
der, and the client area, add visible features and are placed within the
area occupied by the frame window. The frame window is the p¢rc71£ of
these other windows. Presentation Manager windows are organized in
parent-child relationships, and a child window is always displayed
within the area occupied by its parent and overlaps its parent (if a por-
tion of a child window is moved beyond the bounds of its parent, that
portion is cJ}.pped, or made invisible). Note that all child windows are
automatically moved, minimized, hidden, or destroyed together with
their parent window. Note also that a child window can overlap
Creatingawindow 39 .

Wincreatestdwindow
Purpose..
Creates a standard window.

Prototype..
HWND APIENTRY Wincreatestdwindow
(HWND hwndparent, The handle of the parent window; the
value HWND DESKTOP indicates
that the parenTis the Presentation
Manager desktop, which results in a
main (top-level) window; the value
HWND OBJECT creates an object
window-(which has no parent).
ULONG flstyle, Frame window style; can be a
combination of the window styles
(WS_) hsted in Table 2.2 or the frame
styles (FS_) listed in Table 2.3.
PVOID pctlData, Pointer to a ULONG variable that has
been assigned a combination of
window control styles, which have the
FCF_ prefix and are listed in Table 2.4.
These styles specify the control
windows that should be included, and
are combined with the bitwise OR
operator.
pSz pszclientclass, Pointer to a string containing the class
name for the client window; this value
should either be the same as the class
name string that was passed to
WinRegisterclass, or the value
NULL; if the value is NULL, the
system will not create a client window.
PSZ pszTitle, Pointer to a string containing the text
to be displayed in the title bar; this
parameter is ignored if there is no title
bar (that is, FS TITLEBAR is not
specified in flstyle).

• Figure 2.5..
The Wincreatestdwindow Presentation Manager function
• 40 Programmer's Guidetothe os/2Presentation Manager

ULONG styleclient , Style of client window; can be a


combination of the window styles
(WS_) nsted in Table 2.2; this
parameter is ignored if there is no
client window (that is, pszclientclass
is NULL).
ENODULE hood, Resource module handle (applies only
if flstyle includes one or more of
FS ICON, FS ACCELTABLE, or
FS-MENU); i7 the resources are
co=tained in a dynamic-link module,
this parameter should be the module
handle returned by DosLoadModule;
otherwise, it should be NULL,
indicating that the resources are
contained in the .EXE file.
USHORT idResources , Frame window identifier and
identifier of any resources that are
used (applies only if flstyle includes
one or more of FS ICON,
FS ACCELTABLE-, or FS_MENU); all
res-ources used by one standard
window must be assigned the same ID
in the resource script file.
pHve phundclient).. ::indtLeerft:r{#e±:ELeentt°;=a£::.the

Return Value ..
The frame window handle or NULL if the function is
unsuccessful.

Relate d Function..
WinRegisterclass (Figure 2.4)

• Figure 2.5..
Tffe Wincreatestdwindow Presentation Manager f unction (continued)
Creatingawindow 41 .

another child window (known as its sz.Z7Jz.7ig), but a parent window can-
not overlap its child.
The first parameter passed to Wincreatestdwindow (hwndparent)
is the handle of the parent of the frame window. The example program
passes the value HWND_DESKTOP, which is the handle of the dcskfop
window, or the entire Presentation Manager screen. Since its parent is
the desktop window, the frame window can be placed anywhere on the
screen; such a window is known as a 77!¢!.7z or fopJcz7cJ window. Win-
Ci.eatestdwindow returns the handle of the frame window, which is
stored in the variable HFrame.
The second parameter (flstyle) specifies the style of the frame win-
dow. This parameter can be assigned any of the window styles (which
have the WS_ prefix) or frame styles (which have the FS_ prefix); these
styles are combined with the bitwise OR operator (I ). The win-
dow styles apply to windows in general and are described in Table 2.2.
The frame styles apply specifically to frame windows and are described
in Table 2.3.
The example program specifies a single window style, WS_VISIBLE,
which causes the frame window and all its children to be immediately
visible. When you specify WS_VISIBLE, the frame window is given an
initial size and position on the screen that is assigned by the Presentation
Manager shell. If you do not select the WS_VISIBLE style, the frame win-
dow and its children are initially invisible. In this case, you can sub-
sequently render these windows visible by calling Winshowwindow.
The example program does not specify any of the frame styles (FS_)
in the second parameter. As you will see in later chapters, two of the
values that can be passed in this parameter (FS ACCELTABLE, ex-
plained in Chapter 7, and FS_ICON, explained in-Chapter 10) do not
directly affeet the frame style, but rather cause the system to load
specific resources when the window is created.
The third parameter (pctlData) supplies the address of a ULONG
variable that specifies the control windows that are to be included in the
standard window collection (such as a title bar or a system menu). This
variable can be assigned any of the styles listed in Table 2.4 (the con-
stants for these styles have the FCF_ prefix). Note that the FCF_ styles
include not only a set of control windows, but also all of the styles that
can be specified through the scco71d parameter. For example, you can
cause the system to load an icon cz.ffecr by assigning FS_ICON to the
• 42 Programmer's Guide to the os/2 PresentationManager

• Table 2.2.. Presentation Manager Window Styles

Window Style Effect


WS CLIPCHILDREN The system win exclude the area occupied by the
window's children from the window's cZ!.pp!.7ig ¢re¢ (the
area in which it can paint).
WS CLIPSIBLINGS The system will exclude the area occupied by the
window's siblings from the window's clipping area.
WS DISABLED The window is initially disabled, meaning that it cannot
receive mouse input; it can subsequently be enabled by
calling WinEnablewindow.
WS GROUP The window is part of a group (applies only to dialog box
control windows).
WS RAXIMIZED The frame window will initially be maximized.
WS MINIMIZED The frame window will initially be minimized (displayed
as an icon).
WS PARENTCLIP The system will extend the window's clipping area to
encompass the area of its parent.
WS SAVEBITS The system will save the screen area under the window
when it is made visible; when the window is removed,
the system will restore the area it occupied without
sending a WM_PAINT message.
WS SYNCPAINT The system win sc71d a WM_PAINT message directly to
the window procedure whenever any section of the
corresponding window becomes invalid (as opposed to
merely posting the message to the message queue).
WS TABSTOP The window is among those that receive control in
sequence as the user presses the Tab key (applies only to
dialog box control windows).
WS VISIBLE The window is initially visible (the default is for the
window to be initially invisible).
Creatingawindow 43 .

• T¢bJe 2.3.. Presentation Manager Frame styles

Frame Style Effect


FS ACCELTABLE The system will load an
accelerator table.
FS BORDER Frame window is given a
narrow border.
FS DLGBORDER Frame window is given a
standard dialog box border.
FS ICON The system will load an icon
and display it when the
window is minimized (see
Chapter 10).
FS NOMOVEWITHOWNER Do not move the window with
its owner.
FS SHELLPOSITION Window is assigned a default
size and position on the screen
and is initially visible.
FS SIZEBORDER Includes a wide sizing border
window.
FS STANDARD Equivalent to
(FS_ACCELTABLE I FS ICON
I FS SHELLPOSITIONI
FS EASKLIST).
FS SYSMODAL The window is sysfc777 777odflJ,
meaning that it retains the focus
until it is destroyed; this
prevents the user from
switching away from the
window while it maintains
control.
FS TASKLIST The program will be listed
within the Task Manager
window.
• 44 Programmer's Guide to the os/2 PresentationManager

• T¢Z}Jc 2.4.. Presentation Manager Control Window Styles

Frame Style Control Window Included/Style Effect


FCF ACCELTABLE The system will load an accelerator table from the
resource file specified in the hmod parameter to
Wincreatestdwindow.
FCF BORDER Frame window is given a narrow border.
FCF DLGBORDER Frame window is given a standard dialog box border.
FCF HORZSCROLL Horizontal scroll bar.
FCF ICON The system will load an icon and display it when
the window is minimized (see Chapter 10).
FCF MENU Application menu.
FCF MAXBUTTON Maximize box.
FCF MINBUTTON Minimize box.
FCF MINRAX Minimize / maximize box.
FCF NOMOVEVVITHol/VNER Do not move the window with its owner.
FCF SHELLPOSITION Window is assigned a default size and position on
the screen and is initially visible.
FCF SIZEBORDER Wide sizing border.
FCF STANDARD Equivalent to (FCF_ACCELTABLE I FCF_ICON I
FCF MENU I FCF MINMAX I
FCF-SHELLPOSITI-ON I FCF SYSMENU I
FCF-SIZEBORDER I FCF TA3KLIST I
FCF-TITLEBAR).
FCF SYSMENU System menu.
FCF SYSMODAL The window is sysfc777 777odflJ, meaning that it
retains the focus until it is destroyed; this prevents
the user from switching away from the window
while it maintains control.
FCF TASKLIST The program will be listed within the Task
Manager window.
FCF TITLEBAR Title bar.
FCF VERTSCROLL Vertical scroll bar.
Creatingawindow 45 .

second parameter, or by assigning FCF_ICON to the variable pointed to


by the third parameter. (The set of styles that can be assigned to the
second parameter using the FS_ constants are thus a proper subset of
the styles that can be assigned through the third parameter using the
FCF_ styles. The reason for this redundancy is unclear; however, for
the duplicated styles, you have a choice of which parameter you want
to use to specify them.)
The example program specifies the following control window styles
(which are assigned to the ULONG variable CtlData; the address of
CtlData is passed to Wincreatestdwindow):

• FCF MINMAX, which includes a minimize/maximize box win-


dow. This box allows you to reduce the window to an icon on
the screen, or to expand the window to encompass the entire
screen. These actions are performed by clicking the mouse over
the appropriate icon, or through the system menu.
• FCF_SHELLPOSITION, which causes the system to assign the
window an initial size and position on the screen, making it im-
mediately visible. If you do not include this value, the window
will be created with zero dimensions, and will thus be invisible
on the screen until the program calls Winsetwindowpos to ex-
plicitly assign the window dimensions and position.
• FCF_SIZEBORDER, which incorporates a wide sizing border
window that you can use to change the size of the frame win-
dow with the mouse; if you include this window, you can also
change the size through the system menu. Note that if you do
not request creation of a sizing border window, you can give the
frame window a simple border ®y assigning the third
parameter the value FCF_BORDER for a thin border or
FCF_DLGBORDER for a wide border, or by assigning the
equivalent FS_ style to the second parameter). These simple bor-
ders enhance the appearance of the frame window, but do not
allow resizing the window; they are 7?of distinct control windows.
FCF_SYSMENU, which includes a system menu window. The
system menu allows you to minimize, maximize, restore, resize,
or move the frame window, or to terminate the program. You
• 46 Programmer's Guide to the os/2 Presentation Manager

can open this window by clicking on the icon with the mouse, or
by pressing the Alt-Spacebar key combination.
FCF_TASKLIST, which lists the program within the Task
Manager window, allowing the user to switch to the window
or to terminate the program.
• FCF_TITLEBAR, which adds a title bar window at the top of the
frame window that displays the text specified by the fifth
parameter (pszTitle). This control window becomes highlighted
when the frame window is active, and can also be used to move
the window with the mouse (you can additionally move the win-
dow through the system menu).

Note that the styles FCF_MINMAX, FCF_SIZEBORDER, FCF_SYS-


MENU, and FCF TITLEBAR each add a visible feature to the standard
window that can-be acted upon with the mouse to perform a specific
action; including each of these styles also enables the corresponding ac-
tion choice within the system menu (provided that the FCF_SYSMENU
option is also specified). Therefore, for example, if you do not specify
the FCF_SIZEBORDER style, the sizing option will be disabled within
the system menu.
So far, you can see that the call to Wincreatestdwindow creates five
windows: the top-level frame window, and the four child control win-
dows specified by the second parameter. This function call, however,
creates one additional child window, the cJ!.c7tf window, which is
specified through the fourth, sixth, and ninth parameters. The client
window is very important; it occupies the open area inside the other
child windows, and it is the window in which a program normally dis-
plays its data. This window is also the only one for which the example
program supplies a window procedure. All the other windows created
by Wincreatestdwindow use the default system window procedures,
and therefore operate somewhat autonomously; the example program,
however, takes an active role in managing the client window.
The fourth parameter (pszclientclass) specifies the name of the
client window class. The example program passes the same string,
``MAIN'', that was passed to WinRegisterclass. Remember that the call
to WinRegisterclass associated the class name "MAIN" with the win-
dow procedure Wndproc; passing this same string to Wincreatestd-
Window causes the Presentation Manager to pass all messages sent to
Creatingawindow 47 .

the client window to the procedure Wndproc. If a program assigns the


fourth parameter a value of NULL, #o client window is created.
The sixth parameter (styleclient) sets the style of the client window,
and can be any of the WS_ window styles listed in Table 2.2. The ex-
ample program accepts the default styles by passing a value of 0 (unlike
the frame window, the client window is made visible by default). The
ninth parameter (phwndclient) is the address of the variable that is to
receive the client window handle; the program passes the address of the
local variable Hclient. Note that parameters 6 and 9 are ignored if the
fourth parameter is NULL (causing no client window to be created).
The fifth parameter (pszTitle) supplies the text that is displayed
within the title bar. Note that the system prefixes the name of the ex-
ecutable file to the string you pass through this parameter. Since the
example program passes the string

": PM Text Editor"

the system displays the title

"FIG2 27.EXE: PM Text Editor"

As you will see in Chapter 7, you can call the function Winsetwindow
at any time to specify the exact text shown in the title bar.
Finally, the seventh and eighth parameters provide information
regarding the program rcsot/rccs that are used only if the standard win-
dow includes an accelerator table, an icon, or a menu (requested as con-
trofl window styles through the third parameter). Since none of these
frame styles is specified in this program, parameters seven and eight
are assigned a value of 0. Menus, accelerator tables, and resources in
general are discussed in Chapter 7. Chapter 10 describes icons and
other specific resources.
Figure 2.6 illustrates the appearance of the window created by the can
to Wincreatestdwindow. Each of the individual windows is labeled,
except for the frame window, which underlies the entire area and is not
visible. Figure 2.7 illustrates the parent-child relationships of these win-
dows. Note that even though the example program creates only a single
top-level window (the frame), other Presentation Manager applications
currently sharing the screen may also have created top-level windows;
in the diagram, each of these is labeled Other Top-Level Window.
• 48 Programmer's Guide to the os/2 PresentationManager

Wincreatestdwindow is a convenient function for quickly creating


a frame window and a collection of child control windows. You can,
however, also create individual top-level or control windows through
the function Wincreatewindow. This function offers a finer level of

• Figure 2.6..
The basic components of the window created by the example program

DesktopWindow

I I

Other Top-Level Frame Other Top-Level


Window Window Window

Min/Max Sizing Border client System Menu Title Bar


Window Window Window Window Window

• Figure 2.7..
Genealogy of the windows created by `NincreaLtestd:Window
Creatingawindow 49 .

control over the windows it creates. Note also that a program can create
several top-level windows, each of which could subsequently create
one or more child windows.

Step 5: Get and Dispatch Messages


As stated earlier, the system sends many messages to windows to
convey important information and to inform them of a wide variety of
events. When the system sends a message to any of the six windows
that belong to the example program, it places the message in the queue
created by the call to WincreateMsgQueue (when a given program
thread creates a message queue, the system places messages to all
windows created by this thread into the queue). Once the function
main has performed necessary initializations and has created all re-
quired program objects, its sole responsibility is to extract messages
from the message queue and rapidly dispatch them. Accordingly, the
heart of the function main of a Presentation Manager application is a
loop that repeatedly calls WinGetMsg (Figure 2.8) to extract the next
message from the queue, and then calls WinDispatchMsg (Figure 2.9)
to dispatch this message through the system so that the message can be
processed.
Irhe function WinGetMsg extracts the next available message from
the queue, waiting if necessary until a message is available. In general,
WinGetMsg supplies messages in the same order in which they were
inserted into the queue (by the system or by an application); the system,
however, may alter the queue position of certain messages that have a
special priority level (for example, the WM_PAINT message, described
later in the chapter, is given a low priority, and is supplied only after all
other messages waiting in the queue have been extracted). The call to
WinGetMsg in the example program simply removes the 71cxf message,
although, as indicated in Figure 2.8, by setting the last three parameters
you can also extract messages belonging to specific windows, or mes-
sages within a particular range of message identifiers. (Note that you
can call WinpeekMsg to examine queue messages zuz.£feo#£ removing
them.) When WinGetMsg is called, the system copies the contents of
• 50 Programmer's Guide to the os/2 Presentation Manager

WinGetMsg
Purpose..
Extracts the next message from the message queue belong-
ing to the current thread.

Prototype..
BcOL APIENTRY WinGetMsg
(RE hab' Anchor block handle.
PQMSG pqpsg, Pointer to a QMSG structure
that is to be assigned the
content of the message; see the
text for a description of this
structure.
HWND hwndFilter, The ``window filter''; if this
parameter contains a window
handle, only a message for that
window will be obtained; if it
is assigned NULL, the next
message for ¢77y window is
extracted.
USHORT msgFilterFirst , The ID of the first message of
the desired range of messages;
if this parameter and
msgFilterLast are both 0, then
there is no range constraint,
and the next message will be
extracted without regard to its
ID.
USHORT msgFilterLast) ,. The ID of the last message of
the desired range, or 0 if there
is no range constraint.

• Figure 2.8..
The WinGct:Mss Presentation Manager function
Creatingawindow 51 .

Return Value ..
TRUE, unless the message is WM_QUIT, Which causes the
function to return FALSE.

Notes..
This function waits, if necessary, until a message that satis-
fies the specified criteria (if any) is available. It extracts the
71cxf available message, unless the second parameter speci-
fies a particular window, or the third and fourth parameters
indicate a restricted range of message identifiers.

Related Function..
WinDispatchMsg (Figure 2.9)

. Figure 2.8..
The WinGct:Mss Presentation Manager function (continued)

the extracted message into the QMSG structure, the address of which is
paLssed as the second parameter. This structure is defined as follows:

typedef struct _QMSG


(
Hum hund,. /* Handle of the window to which the
/* message is addressed.
USHORT msg,. /* The message identifier.
REJ- mpl ,. /* Message-specific information.
rmJ- mp2 ,. /* More message-specific information.
UI.ONG time,. /* Time message was posted to queue.
POINTL ptl'./* Position of mouse when message was
/* posted to queue.
)
QMSG,.
• 52 Programmer's Guide to the os/2 Presentation Manager

The first field of this structure identifies the particular window to


which the message is sent. The next three fields contain the actual con-
tent of the message. The field msg is the message identifier; for ex-
ample, the message with the identifier WM_PAINT is sent to the client
window whenever this window must redisplay a portion of its data.
The third and fourth fields (mpl and mp2) provide 8 bytes of additional
message information. The meaning of these fields depends upon the
specific message; for example, the WM_CHAR message, sent when
the user presses a key, places the hardware scan code and other infor-
mation in mpl and the character codes in mp2. Versions of the example
program given in later chapters handle a wide variety of messages.

WinDispatchMsg
Purpose..
Causes the system to call a window procedure.

Prototype..
ULONG APIENTRY WinDispatchMsg
(HAD hab, Anchor block handle.
PQMSG pqusg) ,. Pointer to a QMSG message queue structure;
information from this structure is passed to
the window procedure; see the text for a
description of this structure.

Return Value ..
The value returned by the window procedure that is called.

Notes®.

This function is equivalent to calling WinsendMsg, with


parameters corresponding to the appropriate fields in the
QMSG structure.

RelatedFunctions..
WinGetMsg (Figure 2.8)
WinsendMsg (Figure 4.8)

• Figure 2.9..
The WLnDispatchMs8 Presentation Manager function
Creatingawindow 53 .

Once the call to WinGetMsg has extracted a message from the queue,
the example program immediately gives this message back to the sys-
tem by calling WinDispatchMsg, passing the address of the structure
containing the message. WinGetMsg normally returns a value of
TRUE; if, however the extracted message has the identifier WM_QUIT,
then WinGetMsg returns FALSE, which causes termination of the mes-
sage loop. Thus, WM_QUIT is the only message that is not immediately
dispatched, but rather serves to end the program. In the example pro-
gram, the system places this message in the queue when the user selects
the Close option from the system menu. The WM_QUIT message is
described in Figure 2.10.
It might seem that by immediately calling WinDispatchMsg, the
program relinquishes its opportunity to act upon relevant messages;

WM_QUIT
Purpose:
This message is posted to the message queue to terminate
the application.

Parameters..
REARAM mpl Reserved; must be NULL.
rmARAM mp2 Reserved; must be NULL.

Return Value ..
Not applicable (message is not processed by a window
procedure).

Notes..
This message causes WinGetMsg to return FALSE (this
function normally extracts a message from the queue and
returns TRUE). A FALSE return value is a signal that the pro-
gram should end; this message, therefore, would typically
never be passed to a window procedure.

• Figure 2.10..
The WM_QUIT Presentation Manager message
• 54 Programmer's Guide to the os/2 Presentation Manager

however, there will be another opportunity to process certain messages.


WinDispatchMsg causes the system to call the window procedure as-
sociated the window to which the message is addressed. The system
can easily determine the target window, since the handle for this win-
dow is the first field of the message structure. When the system calls the
procedure associated with this window, it passes the first four fields of
the message structure as parameters. Thus, all window procedures
receive the parameters

- hand,.
USHORT msg,.
rmAEun mpl ,.
rmAEun mp2 ,.

with the meanings described above. Each message that is encountered


in the course of developing the example program presented in this book
will be explained in an accompanying figure (such as WM_QUIT in Fig-
ure 2.10). These figures explain the content of the two parameters, mpl
and mp2, that are passed fo the window procedure, as well as the value
that is returned fro77i the window procedure.
In the example program, WinDispatchMsg causes the system to call
a predefined system procedure for messages sent to any window except
the client window. There is a specific predefined procedure for each
type of window; these procedures perform a minimal default action in
response to the message. The predefined window procedure for a
specific control window creates the appearance of the window and
determines the manner in which the window functions. For example,
the window procedure associated with the minimize/maximize box
draws the arrows and causes the frame window to be maximized when
the user clicks on the up-arrow. After the window procedure returns,
control passes back to the function main, which proceeds to extract the
riext message.
If, however, the message is sent to the client window, the system calls
the function Wndproc (contained within the example program and
listed in Figure 2.16) rather than a predefined window procedure. The
system knows to call Wndproc, because when the client window was
created in the call to Wincreatestdwindow, the program passed the
class name ``MAIN", which was associated with the procedure Wndproc
Creatingawindow 55 .

in the previous call to WinRegisterclass. Figure 2.11 reviews the se-


quence of associations that allows the example program to install its
own procedure for the client window. How Wndproc processes the
messages it receives is discussed later in the chapter.

• Figure 2.11..
Steps for implementing the window procedure
• 56 Programmer's Guide to the os/2 PresentationManager

Note that WinDispatchMsg is a sy7icfero77ot4s function, meaning that it


does not return control to the calling program until the window proce-
dure it invokes has returned. Thus, messages are normally handled
serially and in the order they have been placed in the queue. However,
as mentioned later in this chapter and fully explained in Chapter 12, a
given window procedure can start a secondary thread to execute
a lengthy task, and return control immediately to the system. Win-
DispatchMsgretumswhatevervaluewasreturnedbythewindowpro-
cedure; the example program ignores this value.
The description of message handling given so far has been over-
simplified; there are two additional considerations. First, the system is
nottheonlysourceofmessages.Anapplicationcanalsosendamessage
to a given window; a window procedure can even send a message to
itself (this technique greatly simplifies coding of these procedures, and
you will see many examples later in the book). Second, not all messages
are placed in the message queue; when certain messages are sent to a
window, the system calls the window procedure immediately, circum-
venting both the message queue and the message-handling loop in the
function main. Figure 2.12 provides an overview of the Presentation
Manager message-handling mechanism.
You can now see that the expression ``sending a message to a win-
dow" simply means calling the window procedure associated with the
window, passing the contents of the message as parameters (whether or
not the message passes through a queue). Messages are so central to
Presentation Manager applications that these programs are said to have
a 777ess¢gc-b¢scd fl7icfez.£ecf #rc. Sending messages is the primary means for
exchanging information and transferring program control, and receiv-
ing messages is the central activity of the main procedure. The primary
thread of control of a Presentation Manager application thus spends its
time zt7¢z.£!.77g until it receives a message, and then fe¢7idJz.77g the message
appropriately. In contrast, a conventional program actively initiates ac-
tivities at predefined points in its sequence of instructions. A Presenta-
tion Manager program is thus more reactive, and a conventional
program is more proactive. The more passive stance of a Presentation
Manager application makes sense in an environment where basic
resources are intimately shared (specifically, the screen, keyboard, and
mouse), and where the user is given the privilege of manipulating the
Creatingawindow 57 .

program window at almost any time. A Presentation Manager applica-


tion must be highly responsive to the demands of its environment.

Step 6: Release
Presentation Manager Resources
When the function WinGetMsg in the example program extracts
the message WM_QUIT from the queue, it returns a value of FALSE,
and the while loop terminates. Before exiting, the program releases the
resources it has acquired from the Presentation Manager. First it calls
WinDestroywindow (Figure 2.13) to dispose of the frame window and

® Figure 2.12:
The Presentation Manager message-handling mechanism
• 58 Programmer's Guide to the os/2 PresentationManager

all its children, then it calls WinDestroyMsgQueue (Figure 2.14) to free


the message queue, and finally it calls WinTerminate (Figure 2.15) to
sever its final ties with the Presentation Manager. If a program ter-
minates without calling these functions, the Presentation Manager
automatically releases its resources. Thus, these function calls are not
absolutely necessary; including them, however, may give the program a
more orderly appearance as it terminates and removes various objects
from the screen.

• PROCESSING MESSAGES
As explained in the previous section, the system calls the proce-
dure associated with a particular window whenever a message is sent

WinDestroywindow
Purpose..
Destroys the specified window and all its descendant win-
dows.

Prototype..
BOOL APIENTRY WinDestroywindow
(HWND hwnd) ,. Handle of window to destroy.

Return Value ..
TRUE if the function was successful, FALSE otherwise.

Notes..
The window must have been created by the same thread that
calls this function. When a window is destroyed, the
WM_DESTROY message is sent to the window.

• Figure 2.13..
The WLnDestray:W±r\dow Presentation Manager function
Creatingawindow 59 .

to this window. Therefore, all messages sent to the client window cause
the system to call the function Wndproc, which is part of the example
program and is listed in Figure 2.16.
The window procedure must test the second parameter (msg) to
determine the identity of the message, and branch to the appropri-
ate section of code to handle this message. This action is most easily
accomplished with a switch statement. When the window procedure
has completed processing the message, it should return a value of either
TRUE or FALSE, depending upon the particular message. The window
procedure does 7tof have to process all messages; it can select certain
messages to handle and then pass all other messages to the system for
default processing by calling WinDefwindowproc (Figure 2.17).
The function Wndproc processes only the WM_PAINT message and
lets the system worry about all other messages by passing them to Win-
Defwindowproc. The WM_PAINT message is sent to the client window

WinDestroyMsgQueue
Purpose..
Destroys the specified message queue.

Prototype..
BOOL APIENTRY WinDestroyMsgQueue
(IIMQ hmq) ,. The handle of the message queue to be
destroyed.

Return Value ..
TRUE if the function was successful, and FALSE otherwise.

Notes..
This function is normally called after destroying all program
windows, but before calling WinTerminate, in preparation
for program exit.

• Figure 2.14..
The W±nDestrvyMsgQuoue Presentation Manager function
• 60 Programmer's Guide to the os/2PresentationManager

procedure whenever a section of this window needs repainting (that is,


after all or a portion of its data have been destroyed). The actual work of
repainting the window is accomplished by the function Paint, which is
also part of the example program and is explained in the next section.
Note that the window procedure must return before any other mes-
sages waiting in the queue can be extracted and processed. The window
procedure should therefore perform its task rapidly and then return con-
trol. Chapter 12 discusses how to start a secondary thread to allow the
window procedure to perform a lengthy task, yet return control quickly.

WinTerminate
Purpose..
Signals the Presentation Manager that the calling thread has
finished using the services of the Presentation Manager, and
releases all Presentation Manager resources held by this
thread.

Prototype..
BOOL APIENTRY WinTerminate
(HAB hab) ,. The anchor block handle held by the current
thread.

Return Value ..
TRUE if the function is successful, FALSE otherwise.

Notes..
This function is normally called immediately before the pro-
gram terminates, after it has completed calling all other
Presentation Manager functions.

• Figure 2.15..
The W±nTerrwinate Presentation Manager function
Creatingawindow 61 .

DISPLAYING DATA
• WITHIN THE WINDOW
The client window procedure in the example program cans the
function Paint whenever it receives the WM_PAINT message. This func-
tion, hsted in Figure 2.18, serves to update the data displayed within the
program's client window. Specifically, the function clears the entire area
within the window and prints a string at the upper left corner.

When the WM_PAINT Message Is Sent


Before describing the steps required to draw data within a window, it
is important to understand when the function Paint is caued (that is, the
circumstances under which the system sends the WM_PAINT message).
First, the system automaticany sends the WM_PAINT message when the
window is first created during the execution of the Wincreatestdwindow
function. This gives the program an opportunity to create its initial screen
display. The WM_PAINT message is described in Figure 2.19.

lmESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle.
USHORT msg, /* The message.
MPARAI mpl, /* Message-specific information.
Mpj-mp2) /* Message-specific information.
(
switch (msg)
(
case WM PAINT: /* Process window paint message.
return Paint (hwnd, msg, mpl, mp2) ;
default: /* Perform the default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;
)

} /* end Wndproc */

• Figure 2.16..
The function Wr\dproc of the example progran
• 62 Programmer's Guide to the os/2 Presentation Manager

Second, the system sends WM_PAINT whenever the entire window,


or any portion of it, becomes I.71z7¢Jz.d. An invalid area of a window is a
section that needs to be displayed, but for which screen data are not
available; it is therefore a section of the window that requires updating.
For example, when the user increases the size of a window (by resizing,
maximizing, or restoring it from an icon), the system does not have data
for the newly uncovered area and therefore issues a WM_PAINT mes-
sage to force the client window procedure to update the display. Also, if
another window is placed on top of the client window, the system does
not normally save the overwritten data; therefore, when the overlying
window is removed, the system sends the client window a WM_PAINT

WinDefwindowproc
Purpose..
Passes a message to the system for default processing.

Prototype,
MRESULT APIENTRY WinDefwindowproc
(HWND hwnd, Handle of the window to which the message
was originally sent.
USHORT msg, Message identifier.
REARAM mpl , Message parameter 1.
I@ARAM mp2) ,. Message parameter 2.

Return Value ..
The return value depends upon the specific message.

Notes
A window procedure normally calls this function to handle
messages that it does not want to process itself. The window
procedure should pass this function the s¢777c parameters that
it received when it was invoked.

• Figure 2.17..
The WLnDef:Windowproc Presentation Manager function
Creatingawindow 63 .

message. (If, however, the overlying window was created with either
the CS_SAVEBITS or the WS_SAVEBITS style, the system will automat-
ically save and restore the overwritten data, and will not need to send a
WM_PAINT message.) Note that when the window is 777oz7cd, the sys-
tem directly transfers the data without sending WM_PAINT.

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window rectangle, in window coordinates
static char Message [] = /* Text to display.
''This line is displayed by the window procedure.";

/*** Obtain a handle to a presentation space. ********************************/

Hpresspace = WinBeginpaint /* Returns presentation space handle.


(hwnd, /* Window handle.
0, /* 0 requests a cache presentation space.
0) ; /* Address of variable to set to update region: none.

/*** Obtain the coordinates of the client window. ****************************/


WinQuerywindowRect
(hwnd, /* Window handle. */
&Rect) ; /* Structure to receive coordinates. */
/*** Erase the existing contents of the screen. ******************************/
WinFillRect /* Draws a filled rectangular area.
(Hpresspace, /* Presentation space handle.
&Rect, /* Structure containing window coordinates.
CLR WHITE); /* Color to use (white).

/*** Print the line of text. ************************************************/

WinDrawText /* Draws a single line of formatted text into a rectangle. */


(Hpresspace /* Presentation space handle. */
Oxffff' /* Length of string: Oxffff means 0 terminated.*/
Message, /* Text to be displayed.
&Rect ' /* Coordinates of rectangle containing text.
CLR BI]ACK, /* Foreground color.
cm-WHITE , /* Background color.
/* Drawing specifications:
DT_LEFT I /* Left justify.
DT TOP) ; /* Place at top of window.
/*** Release presentation space / revalidate window. *************************/
WinEndpaint (Hpresspace) ; /* Tells Presentation Manager that */
/* redrawing is complete. */
return FALSE;

) /* end Paint */

• Figure 2.18..
The function Halul of the example program
• 64 Programmer's Guide to the os/2PresentationManager

In general, a Presentation Manager program needs to write data to


the window under two circumstances. First, it must update the window
display in response to cxfc7'7i¢J events, such as the user enlarging the
window. In this case, the system automatically sends a WM_PAINT
message. Second, the program must create an initial screen display and
update this display whenever there is a change in the program's visible
data (for example, the client window of a text editor must be updated
whenever the user enters a new character into the file). As you have
seen, the system automatically issues a WM_PAINT message at win-
dow initialization to allow drawing the opening window display. Also,
as you will see later in the book, you can trick the system into sending a
WM_PAINT message at any time by explicitly invalidating sections of

WM PAINT
Purpose..
This message is sent by the system to a window whenever
the entire window, or any portion of it, needs redrawing.

Parameters..
REARAM mpl NULL (Reserved value).
MPARAM mp2 NULL (Reserved value).

Return Value ..
NULL.

Notes..
When this message is received, the window procedure must
explicitly draw the data within the invalid section of the win-
dow. The function WinBeginpaint (Figure 2.20) supplies the
coordinates of the invalid region, and WinEndpaint (Figure
2.21) informs the Presentation Manager that the window is
now completely valid.

• Figure 2.19..
The WM_PAINT Presentation Manager message
Creatingawindow 65 .

the screen. Therefore, all window output can be handled through the
section of the window procedure that responds to the WM_PAINT mes-
sage. Accordingly, you can cc71£r¢J!.zc all screen-drawing code within a
single all-purpose function (in this example, the function Paint), and
you do not need to have drawing functions scattered throughout the
program. This is a fortunate design feature, since, as you will see in the
next section, drawing within a window is not a trivial task.

Steps for Updating the Screen


Although the function Paint merely clears the window and dis-
plays a single string, it serves to illustrate the essential steps required to
update a window display under the Presentation Manager.
Before writing to the window, the function Paint calls WinBegin-
Paint (Figure 2.20); after it has completed updating the display, it calls
WinEndpaint (Figure 2.21). These two functions must surround all
other functions that generate output to the window, and they serve two
primary purposes. First, as mentioned in the previous section, the
WM_PAINT message is sent whenever a section of the window is in-
valid. Calling the functions WinBeginpaint and WinEndpaint signals
the system that you are updating the window display and that the win-
dow therefore no longer contains an invalid region; in other words,
these functions reset the invalid area to NULL.
Second, WinBeginpaint provides a handle to a prcsc7z£#fz.o7i sp¢cc.
Under the Presentation Manager, you do not draw directly onto a
physical device, such as the screen or a printer. Rather, you draw onto
an abstract surface known as a presentation space. A presentation space
is implemented as a data structure within the Presentation Manager,
and it has a set of characteristics that are independent of any physical
device, such as a current font and current drawing colors. Before you
can produce output, however, you must associate the presentation
space with a physical device, known as the dezJz.cc co7ifcxf . The Presenta-
tion Manager provides several functions for creating presentation
spaces and associating them with device contexts; also, there are several
different types of presentation space.
Calling WinBeginpaint, however, is a convenient method for per-
forming both steps in a single function call (that is, obtaining a presen-
tation space fl77d associating it with a device context). This function
• 66 Programmer's Guide to the os/2 Presentation Manager

WinBeginpaint
Purpose..
Obtains a handle to a presentation space that is associated
with the specified window.

Prototype..
HPS APIENTRY WinBeginpaint
(IIWND hwnd, Handle of the window to receive data.
Hps hps , Handle of an existing presentation
space to be associated with the
window given by hwnd; if this
parameter is NULL, the system
supplies a cache presentation space.
PRECTL prclpaint) ,. Address of a RECTL structure to
receive the window coordinates of the
smallest rectangle bounding the
invalid region(s) of the window; this
structure is defined in Figure 2.22.

Return Value ..
The handle of the presentation space.

Notes..
The presentation space obtained by this function is ready for
drawing onto the specified window. Note that after this
function is called, the system considers the window data
completely valid (that is, the invalid region of the window is
set to NULL). You must call WinEndpaint after the window
has been updated.

RelatedFunction..
WinEndpaint (Figure 2.21)

• Figure 2.20..
The W±nBeginp aint Presentation Manager f unction
Creatingawindow 67 .

returns a handle to a presentation space that is already associated with


a window (the window specified through the first parameter) and is
ready to receive output. The example program passes 0 as the second
parameter, which causes WinBeginpaint to supply a cocfec presentation
space; this type of presentation space is provided from the system's in-
ternal cache of presentation spaces, and it can be allocated quickly and
without consuming additional memory. The call to WinEndpaint
releases the presentation space after the window is updated. Note that

WinEndpaint
Purpose..
Signals the system that the updating of the window (which
occurs typically in response to a WM_PAINT message) is
complete.

Prototype..
BOOL APIENTRY WinEndpaint
(Eps hps) ,. Handle of presentation space that was used
for painting the window.

Return Value ..
TRUE if the function was successful, FALSE otherwise.

Notes..
After you have called WinBeginpaint and have completed
updating the window display, you must call WinEndpaint.
If the call to WinBeginpaint supplied a cache presentation
space, WinEndpaint returns this presentation space to the
cache.

Related Functions ..
WinBeginpaint (Figure 2.20)

• Figure 2.21..
The W±nEndp ELiul Presentation Manager f unction
• 68 Programmer's Guide to the os/2 PresentationManager

you must call WinEndpaint before returning from processing the cur-
rent message.
Once a handle to a presentation space has been secured, the function
Paint obtains the current dimensions of the client window by calling
WinQuerywindowRect (Figure 2.22). This function assigns the dimen-
sions to a RECTL structure (defined in Figure 2.22); note that since the

WinQuerywindowRect
Purpose..
Returns the coordinates of the specified window.

Prototype..
BOOL APIENTRY WinQuerywindowRect
(I]wND hwnd, Window handle.
PRECTL prcIDest) '. 5:L£:#tto°raecRe¥vceTtE:t:::r¥::#eesfi:nfetfe
window.

Structure..
typedef struct
(
LONG xLeft,.
LONG yBottom,.
LONG xRight ,.
LONG yTop,.
)
RECTL,.

RetumValue..
Returns TRUE if successful, and FALSE otherwise.

Notes..
The coordinates are given relative to the lower left comer of
the window; thus xLeft and yBottom are both 0.

• Figure 2.22..
The WinQuerywindowRect Presentation Manager f unction
Creatingawindow 69 .

dimensions provided are relative to the lower left corner of the window,
the fields xLeft and yBottom are both set to 0. The window dimensions
are used by the two subsequent function calls.
The function Paint next erases the former contents of the window by
calhng WinFillRect (Figure 2.23). WinFillRect draws a rectangle filled
with a specified color; by passing the dimensions of the entire window,
and by specifying the desired background color (white), this function ef-
fectively clears the window. Note that WinFillRect is passed the handle
to the presentation space obtained from the call to WinBeginpaint.
Once the screen has been filled with the desired background color,
the program calls WinDrawText (Figure 2.24) to draw a string within
the window. This function justifies a string within a specified rectangle.
The program sets this rectangle to the dimensions of the entire screen
and requests that the string be justified at the top and left of the rec-
tangle; therefore, the string is drawn starting at the upper left corner of
the window. WinDrawText also allows you to specify the foreground
and background colors used to draw the string. The function call selects
a black foreground, and it also selects a white background to match the
background painted by WinFillRect. The window thus displays black
letters on a white background.

WinFillRect
Purpose..
Draws a rectangle filled with a specified color.

Prototype..
BOOL APIENTRY WinFillRect
(HPS hps, Handle of the presentation space onto which
the rectangle is to be drawn.
PRECTL prcl, Pointer to a RECTL structure containing the
coordinates of the rectangle to draw; see
Figure 2.22 for the definition of this structure.

• Figure 2.23..
The WLnFLIIRect Presentation Manager f unction
• 70 Programmer's Guide to the os/2 PresentationManager

LONG IColor) ,. Color to be used to fill the rectangle; the


following basic colors may be specified:
CLR WHITE
CLR BLACK
CLR BLUE
CLR-RED
CLR PINK
CLR GREEN
CLR CYAN
CLR YELLOW
CLR DARKGRAY
CLR DARKBLUE
CLR DARKRED
CLR DARKPINK
CLR DARKGREEN
CLR DARKCYAN
CLR BROWN
CLR-LIGHTGRAY
Inaddition7youcanspecifyoneofthe
following identifiers :

Identifier Meaning
CLR BACKGROUND Default window
color
CLR NEUTRAL Default
foreground color

Return Value ..
TRUE if the function was successful, FALSE otherwise.

• Figure 2.23..
The WLnErllRect Presentation Manager f unction (continued)

Note that the function Paint makes no attempt to determine the sec-
tion of the window that is actually invalid, but rather redraws the entire
window. Subsequent versions of the example program enhance ef-
ficiency by updating only the invalid section.
Creatingawindow 71 .

WinDrawText
Puxpose..
Prints a text string within a specified rectangle, using the cur-
rent font.

Prototype..
SHORT APIENTRY WinDrawText
(Hps hps , Handle of the presentation space on which
the string is to be drawn.
SHORT cchText , Number of characters contained in the
string; the value Oxffff means that the string
is null-terminated and the function will
calculate its length.
PCH pchText, Pointer to the string to print.
PRECTL prcl, Pointer to a RECTL structure containing the
dimensions of the rectangle inside of which
the string is to be drawn; see Figure 2.22 for
the definition of this structure.
LONG clrFore, The foreground color; see Figure 2.23 for a
list of colors you can specify.
LONG clrBack, The background color; see Figure 2.23 for a
list of colors you can specify.
USHORT rgfond) ,. The mode in which the string is to be drawn;
you may assign one or more of the following
values:

Value Meaning
DT LEFT Left-justify text.
DT CENTER Center text.
DT RIGHT Right-justify text.
DT VCENTER Vertically center text.
DT TOP Top-justify text.
DT BOTTOM Bottom-justify text.

Return Value ..
The actual number of characters drawn.

• Figure 2.24..
The WLnDra;wTch Presentation Manager f unction
• 72 Programmer's Guide to the os/2 PresentationManager

BUILDING A PRESENTATION
• MANAGER APPLICATION
Figures 2.25, 2.26, and 2.27 (at the end of the chapter) list the three
basic files used to build the example program: a MAKE file, a linker
definition file, and the complete C source code file.
The MAKE file in Figure 2.25 can be used to prepare the example pro-
gram by means of the Microsoft MAKE utility. See the Microsoft
documentation for instructions on using this utility. The C source code
is compiled with the following command line:

cl /Tnt. /a /7;p /&R;Ns FT:I :R._2:I .a

The command-line switches have the following meanings:

Switch Meaning
/W2 Provides a high level of compiler warnings; the de-
fault level is 1, and the highest level is 3. This flag is
helpful for compiling fl77y type of C program, espe-
cially Presentation Manager applications, which in-
volve many data types and many possibilities for
type nrismatches.
/c Compiles without linking. The linker is invoked on a
separate line in the MAKE file.
/Zp Packs structures (that is, places each structure field on
the next available byte address rather than aligning
certain fields on even addresses); this option is impor-
tant because certain OS/2 or Presentation Manager
API functions may assume that the structures passed
to them are packed.
/G2 Enables instructions specific to the 80286 and later
model processors. Since the Presentation Manager re-
quires at least the 80286 processor, why not allow the
compiler to take advantage of these more efficient
instructions?
Creatingawindow 73 .

/Gw This option should be used for preparing a Presenta-


tion Manager program that contains a window proce-
dure; it causes the procedure to save the original
value of the DS register on function entry, set DS to
the appropriate value during execution of the proce-
dure, and then restore the original value of DS before
the procedure returns. These steps (referred to as the
Window's prolog and epilog) allow a Presentation
Manager dynamic-link module to call the window
procedure.
/Gs Disables the calls made to the C stack-checking
routine at the beginning of each function; the C stack-
checking routine is not compatible with the Presenta-
tion Manager, since it attempts to write to the screen
using conventional teletype-style screen output,
which is not allowed within the Presentation
Manager windowed environment.

After the program is compiled, it is linked using the fouowing command:

link FIG2 27.OBT,, NUL, OS2.LIB, FIG2 26.DEF

As mentioned in Chapter 1, OS2.LIB is the import library containing


dynamic-link records for the OS/2 and Presentation Manager API func-
tions. In addition, you may need to specify the name of the protected
mode version of the standard C library if you have not given this library
the standard name (SLIBCE.LIB; see your compiler documentation).
The command also specifies the name of a Jz.77kcr dc¢.71!.I !.o77 fi.Jc
(FIG2_26.DEF, listed in Figure 2.26). A linker definition file contains in-
formation required to prepare Presentation Manager and certain OS/2
kernel applications. The definition file for the example program con-
tains the following statements:

Command Effect
NAME FIG2 27 Names the application and specifies
the program as an application rather
than a dynamic-link module.
• 74 Programmer's Guide to the os/2 PresentationManager

PRO"ODE Specifies that the program will run


only in protected mode; including this
statement including this statement
may result in a small reduction in the
program size.
HEAPSIZE 1024 Requests a program heap of 1024
bytes; this memory is used for
dynamic memory allocation.
STACKSIZE 8192 Requests a program stack of 8192 bytes.
EXPORTS Wndproc Exports the window procedure so that
it can be called by Presentation
Manager dynamic-link modules. yo#
must list all window procedures in the
EXPORTS statement .

Finally, the complete C source code is listed in Figure 2.27. Many of the
fouowing chapters in this book win also hit the complete set of files you
need to build the version of the text editor presented in that chapter. These
filesaegivenattheendofthechapter,andconsistinitiallyofaMAREfile
(.MAK), a hiker definition file (.DEF), and a C source file (.C). Chapter 8
will add resource files (.DLG and .RC) and a header file (.H) to this set.

• CONCLUSION
In this chapter, you have seen the basic sequence of function cans
that constitute a minimal Presentation Manager application. A feature
common to many of these function calls is the use of handles. In
general, when a Presentation Manager function allocates an object to an
application (such as a window), it returns a handle; this handle must be
supplied to subsequent function calls that manipulate the same object,
and it serves to identify the specific instance of a given type of object.
The actual value of a handle has meaning only to the system, and not to
the application (such variables or parameters are therefore known as
``magic cookies''). The first handle supplied to an application is the
anchor block handle, which is returned by Winlnitialize and identifies
the basic set of resources and information that the Presentation
Creatingawindow 75 .

Manager maintains for the application. This handle must be passed to


several other system functions. Many other Presentation Manager func-
tions return additional handles; in the example program in this chapter,
you have seen the following handles:

• The anchor block handle


• Amessagequeuehandle
• Window handles for the frame and client windows
• Apresentationspacehandle

Although the example program will become much larger and more
complex in subsequent chapters, the version presented here illustrates
most of the essential concepts involved in programming under the
Presentation Manager. If you are accustomed to a conventional
programming environment, some of these concepts may now seem
somewhat alien; however, as the basic ideas are reinforced in sub-
sequent chapters, you will not only become more comfortable with
these concepts, but you will probably come to enjoy the unique and in-
teresting logic of the Presentation Manager.

# Figure 2. 25
# This MAKE file prepares the program of Figures 2.26 and 2.27
#
FIG2 - c|27.ORE
/Ti(2
: FIG2 27.C
/c /rz;p /r:%NS FT!f :2_2:J .C

FIG2 - link
27.EXE : FIG2 27.OEU FIG2 26.DEF
/NOD FIG2 27.OBT,, NUL, OS2.LIB SLIBCE.LIB, FIG2 26.DEF

• Figure 2.25..
A MAKE file for preparing the example program

Figure 2.26
; Linker® definition file for the program listed in Figure 2.27
NAME FIG2 27
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 2.26..
A linker definition file for preparing the example program
• 76 Programmer's Guide to the os/2 Presentation Manager

/*
Figure 2.27
Version 1 of the Presentation Manager text editor example program.
This version performs the following tasks:
o Initializes the Presentation Manager system
o Creates a message queue
o Registers a window procedure
o Creates a standard window
o Processes window messages
o Writes a line of text at the top of the window from the
window procedure
o Relinquishes Presentation Manager resources before termination
*/
#include <OS2.H>

/*** Declare window procedure. ***********************************************/

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

void main ()
(
HAB HAncBlk; /* Anchor block handle.
HMQ HMesQue; /* Message queue handle.
HWND HFrame, Hclient; /* Frame/client window handles.
QMSG QueMess; /* Message queue structure.
ULONG CtlData = /* Control windows to include.
FCF MINMAX /* Minimize/maximize box.
FCF-SHELLPOSITI0N /* Make window visible on screen.
FCF-SIZEBORDE-R /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
/*** Initialize the Presentation Manager and obtain an anchor block handle. **/
HAncBlk = Winlnitialize /* Returns an anchor block handle. */
(0) ; /* Initialization options: must be 0. */
/*** Create a message queue for the current thread. **************************/
HMesQue = Wincrii::¥:!%Teue ;: :::::::b::::::::i:¥:u:e:::d:::auLt size. ;;

/*** Register a window procedure. ********************************************/


WinRegisterclass
(HAncBlk, /* Anchor block handle.
''mlN„ , /* Window class name.
Wndproc , /* Window procedure associated with class.
OL, /* Class style: no styles specified.
0); /* Bytes of data storage for each window.

• Figure 2.27..
The source code file for the example program
Creatingawindow 77 .

/*** Create a standard window. ***********************************************/


HFrame = Wincreatestdwindow /* Returns handle to frame window.
(HWND DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style.
&cEIData, /* Address of control data.
''MAIN„ ,
/* Client window class name.
'': PM Text Editor", /* Text for title bar.
OL, /* Client window style: none specified.
0, /* Resource module handle: none.
0' /* Resource identification: none
&Hclient) ; /* Address to receive client window hand.
/*** Main message-handling loop. *********************************************/
while (WinGetMsg /* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure.
0, /* Window filter: any window.
0, /* First message identifier: n/a.
0)) /* Last message identifier: n/a.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

/*** Relinquish Presentation Manager resources and terminate application.


WinDestroywindow (HFrame) ; /* Eliminate the window.
WinDestroyMsgQueue (HMesQue) ; /* Eliminate the message queue.
WinTerminate (HAncBlk) ; /* Sever ties with the Presentation
/* Manager and release resources.
} /* end main */

/*** The window procedure and subroutines. ***********************************/


MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle.
USHORT msg, /* The message.
MPAEN mpl, /* Message-specific information.
MPAEN mp2) /* Message-specific information.
(
switch (msg)
Ease wM PAINT: /* Process window paint message.
return Paint (hwnd, msg, mpl, mp2) ;
default: /* Perform the default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;
)

• Figure 2.27..
The source code file for the example program (continued)
• 78 Programmer's Guide to the os/2 Presentation Manager

} /* end Wndproc */

/*** Function for processing the window paint message. ***********************/


mESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window rectangle, in window coordinates
static char Message [] = /* Text to display.
''This line is displayed by the window procedure.";

/*** Obtain a handle to a presentation space. ********************************/


Hpresspace = WinBeginpaint /* Returns presentation space handle. */
(hwnd, /* Window handle. */
0, /* 0 requests a cache presentation space. */
0) ; /* Address of variable to set to invalid region: none.*/
/*** Obtain the coordinates of the client window. ****************************/
WinQuerywindowRect
(hwnd, /* Window handle. */
&Rect) ; /* Structure to receive coordinates. */
/*** Erase the existing contents of the screen. ******************************/
WinFillRect /* Draws a filled rectangular area.
(Hpresspace, /* Presentation space handle.
&Rect, /* Structure containing window coordinates.
CIA WHITE) ; /* Color to use (white).

/*** Print the line of text. ************************************************/


WinDrawText /* Draws a single line of formatted text into a rectangle.
(Hpresspace /* Presentation space handle
Oxffff' /* Length of string: Oxffff means 0 terminated.
Message , /* Text to be displayed.
&Rect, /* Coordinates of rectangle containing text.
CLR BIiACK, /* Foreground color.
CIIR-WHITE, /* Background color.
/* Drawing specifications:
DT_LEFT I /* Left-justify.
DT TOP) ; /* Place at top of window.
/*** Release presentation space / revalidate window. *************************/
WinEndpaint (Hpresspace) ; /* Tells Presentation Manager that */
/* redrawing is complete. */
return FALSE;

) /* end Paint */

• Figure 2.27..
The source code file for the example program (continued)
i pter three

Managing
Memory
81.

.I
he version of the Presentation Manager text editor pre-
sented in this chapter accepts the name of a file from the
command line, reads the file into an internal buffer, and
then displays the beginning of the file within the win-
dow. Although this version displays only as many lines from the head
of the file as will fit within the client window, the entire file is loaded
into data structures in memory that will allow subsequent versions of
the program to efficiently access, display, and manipulate the file data.
The memory used to store the file is allocated dynamically, so that the
program can accommodate files of various lengths without reserving a
data segment of fixed arbitrary size. Also, if the user enlarges the win-
dow on the screen, the program automatically displays additional lines
from the file so that the window area is always filled (provided the file
is sufficiently large).
In this chapter, you will learn how to use the Presentation Manager
heap-management functions for dynamically allocating blocks of
memory; you will learn how to handle Presentation Manager errors;
and you will learn how to display multiple lines of text within a win-
dow in a manner that is independent of the size of the window and the
resolution of the display device. The chapter also discusses the design
of the data structures used to store and manage the file data, describes
the collection of programming macros provided by OS/2, and presents
several new Presentation Manager functions and messages. Finally, the
program describes the techniques for loading and displaying specific
Presentation Manager fonts.
Note that the complete source code listing for the current version of
the example program is given in Figure 3.33, at the end of the chapter.
Several of the Presentation Manager functions called by this program
require portions of the OS/2 header files that are not automatically in-
corporated simply by including OS2.H. To force the compiler to include
the required header information, the program defines two constants
Z7e/ore including OS2.H. Defining the constant INCL_WIN causes in-
clusion of all header information for the window-management (Wz.7£)
functions, and defining INCL_GPI includes all information for the
graphics (Gpl.) functions. Table 3.1 lists the most general of these con-
stants and the header data they cause the compiler to include. In addi-
tion to the constants listed in this table, there are many other constants
• 82 Programmer's Guide to the os/2 Presentation Manager

that you can define to include smaller portions of the header informa-
tion; for example, the constant INCL_WINHEAP incorporates informa-
tion for only a s#Z7sef of the window-management functions
(specifically, the heap-management functions, such as those described
in this chapter). In Table 3.1,. the expression `foy default'' refers to por-
tions of the header files that are automatically included through the
#include <OS2.H> statement.

• Table 3.1.. Constants f or Including Presentation Manager Hfq4_gr_|]|fg]]]|_a_±±o_1

Constant Header Information Included


INCL PM AJJ Presentation Manager header
information (this constant is
equivalent to defining all of the
following constants).
INCL WIN All header information for
window-management ( Wt.7t) functions
(some of this information is included
by default).
INCL GPI All header information for graphics
(Gp!.) functions (some of this
information is included by default).
INCL DEV All header information for device
support (Dcu) functions (some of this
information is included by default).
INCL AVIO Header information for advanced Vio
(V!.o) functions (none of this
information is included by default).
INCL SPL Header information for spooler (SpJ)
functions (none of this information is
included by default).
INCL ERRORS All constant definitions for error codes
returned by Presentation Manager
functions.
ManagingMemory 83 .

• MANAGINGTHEHEAP
In the example program, the functions and data stmctures used to
read the file and manage the internal data buffer are grouped into a dis-
tinct module; this module is located within the single source code file,
although it could easily be placed within a separate file. The module
consists of a public section and a private section. The public section
comprises the constant definitions, variable definitions, and function
declarations used by both the function module and the main Presenta-
tion Manager program; it is listed in Figure 3.1. The private section con-
sists of the functions themselves and the data structures and definitions
used internally by these functions.
The public section is placed above the function main in the example
program, and the private section is placed near the end of the file (see
the complete listing in Figure 3.33). If the private section of the module
were located in a separate sourc`e file, the public section could be placed
in a header file that is included both by the module and by the main
program. The reason for encapsulating the file-handling functions
within a separate module is to simplify the logic of the main application
and to permit you to modify the implementation details of the buffer-
management code without disturbing the main program. Note that
under OS/2, you can also implement modules of supporting functions

/*** Declarations / definitions for file-and buffer-management module. ******/


#def ine LINEBUFSIZ /* Size of buffer for holding lines.
#def ine ERROPEN /* Error: opening file.
#def ine ERRTOOBIG /* Error: file too large.
#def ine ERRMAXLINES /* Error: maximum file lines exceeded.
#def ine ERRALLOC /* Error: heap allocation.
void Buf Init (void) /* Initializes buffer management module
char *ErrorMessage (int ErrorNumber) ; /* Returns error message string
int ReadFile (char *FileName) ; /* Reads file into editor buffer.
SHORT GetLineLength (int Line) ; /* Gets length of line in buffer.
PCH GetLineAddr (int Line) ; /* Gets address of line in buffer.
int LastLine = 1; /* Number of last line in buffer.
HHEAP HHeap = NULL; /* PM heap handle.

• Figure 3®1..
The public declarations of the file |buffer-management module
• 84 Programmer's Guide to the os/2 Presentation Manager

as dynamic-link libraries, which could be shared by several application


programs (see the discussion of dynamic linking in Chapter 1).
Before ihitializing the Presentation Manager and creating the mes-
sage queue, the function main calls two procedures belonging to the
buffer-management module. First, it calls Buflnit (listed in Figure 3.2)
to initialize the module; this function obtains and stores the selector and
offset of the temporary buffer LineBuffer, which will be used by other
functions in the module for holding and manipulating individual lines
of the file. Note that this buffer is assigned a size of LINEBUFSIZ, which
is the maximum line length (including the newline character and the
terminating null) that can be handled by the program.

void Buf Init (void) /* Initializes the buffer-management module. */


(
PCH Farptr;

/*** Obtain selector and offset of temporary line buffer. ********************/


Farptr = (char far *)LineBuffer;
Lineselector = SELECTOROF (Farptr) ;
Lineoffset = OFFSETOF (Farptr) ;

} /* end Buflnit */

• Figure 3.2..
The function Buflrhi from the exanple program

To extract the selector and offset, the program uses two of the macros
that are supplied by the OS/2 header files. The macro SELECTOROF
extracts the selector from a far address, and OFFSETOF extracts the of-
fset. Some of these macros are supplied by the general OS/2 header files
(such as OS2DEF.H), and some are provided by the header files specific
to the Presentation Manager (for example, PMWIN.H). Table 3.2 lists a
collection of the more useful macros, including all of those used by the
versions of the example program presented in this book. The macros
specific to the Presentation Manager can be grouped into the following
categories, according to the functions they serve:

• Macros for preparing parameters to pass to window procedures.


These macros, which have the form MPFROM ..., are commonly
ManagingMemory 85 .

used when sending messages to windows through the Winsend-


Msg function, to be explained in Chapter 4.
Macros for extracting values from the message parameters
received by window procedures, which are named mpl and
mp2 in the example program. These macros have the form
...FROMMP; an example is SHORT2FROMMP, which is used by
the function Size, explained later in the chapter. There are also
several special-purpose macros for extracting information from
the parameters for specific messages; an example is CHARMSG,
which can be used to isolate specific portions of the parameters
passed with the WM_CIIAR message, explained in Chapter 6.
Macros for preparing values to be returned by window proce-
dures (which have the return type MRESULT). These macros
have the form MRFROM .... They are not used by the window
procedures of the example program, which simply return TRUE
or FALSE.
Macros for extracting specific values from the number returned
/ro777 a window procedure. These macros have the form ...FROM-
MR, and can be used to process the value returned by the func-
tion WinsendMsg (which returns whatever value is returned by
the window procedure to which the message was sent).

• Tlable 3.2.. Usef ul os!2_ Macros

General-Puxpose Macros

Macro Type Purpose


MA;KEP(Sel, of f ) PVOID Creates an untyped far pointer from
selector SCJ and offset o#.
SELECTOROF(p) USHORT Extracts the selector from far pointer p.
OFFSETOF(p) USHORT Extracts the offset from far pointer p.
MAKETYPE (tJ, fypc) * Converts variable zJ to type fypc.
• 86 Programmer's Guide tothe os/2Presentation
Manager

• Tlable3.2.. Use i OS|2 Macros (continued)

Macro Type Purpose


FIELDOFFSET(fypc,¢.eJd) SHORT Calculates the byte offset of field
¢.cJd within the structure of type ftypc.
MAKELONG(z, fe) LONG Combines low-order value J and
high-order value fe to make a 32-bit
signed quantity.
MAKEULONG(J, fe) ULONG Combines low-order value J and
high-order value fe to make a 32-bit
unsigned quantity.
RAKESHORT(z, fe) SHORT Combines low-order value J and
high-order value fe to make a 16-bit
signed quantity.
RAKEusHORT(z, fe) USHORT Combines low-order value J and
high-order value 7z to make a 16-bit
unsigned quantity.
LOBYTE(zt7) UCHAR Extracts the low-order byte from 16-
bit quantity zt,.
HIBYTE(zo) USHORT Extracts the high-orderbyte from 16-
bit quantity ztl
LOUCRAR(zt7) UCHAR Extracts the low-order byte from 16-
bit quantity zu; same as LOBYTE.
HIUCHAR(zu) USHORT Extracts the high-order byte from 16-
bit quantity ztJ; same as HIBYTE.
LOUSHORT(J) USHORT Extracts the low-order word (16-bit
value) from the 32-bit quantity J.
HIUSHORT(J) USHORT Extracts the high-order word (16-bit
value) from the 32-bit quantity J.
ManagingMemory 87 .

• Tlable 3.2.. Use | oS|2 Macros (conttyT4

Macros f or Preparing Message Parameters

Macro Type Purpose


MPFROMP(p) MPARAM Makes a message parameter type
from pointer p.
MPFROMHWND(fezt77id) MPAF" Makes a message parameter type
from window handle Jzw7id.
MPFROMcrm(cfe) MPARAV Makes a message parameter type
from character cfe.
MPFROMSHORT(s) MPARAM Makes a message parameter type
from the quantity s.
MPFROM2SHORT(sl , s2) MPARAM Makes a message parameter type
consisting of the low-order value sl
and the high-order value s2.
MPFROMSH2cH(s,t4cfel,t4cfe2) MPARAM Makes a message parameter type
consisting of the low-order value s
and the high-order value formed
from #cJzl (low) and #cfe2 (high).

MPFROMLONG(I) MPARAM Makes a message parameter type


from the 32-bit quantity I.

Macros f or Extracting Irofor'l'nation from Message Paraneters

Macro Type Purpose


PVOIDFROMMP(77tp) PVOID Converts message parameter 7#P to
an untyped far pointer.
HWNDFROMMP(77ip) HVVND Converts message parameter 77ZP to a
window handle type.
CRARIFROMMP(77zp) UCRAR Extracts the lowest-order byte of
message parameter 777P.
CRAR2FROMMP(77zp) UCHAR Extracts the second byte (from the
low-order end) of message
parameter 7#P.
C±3FROMMP(77tp) UCRAR Extracts the third byte (from the low-
order end) of message parameter 777p.
•88 Programmer's Guide to the OS/2 Presentation Manager

• Tlable3.2.. Use i OS/2 Macros (continued)

Macros f or Extracting Inf ormation from Message Parameters (continued)

Macro Type Purpose


CHAR4FROMMP(77tp) UCHAR Extracts the highest-order byte of
message Parameter 77tp.
SHORTIFROMMP(77ip) USHORT Extracts the low-order word (16-bit
value) from message parameter 77ip.
SHORT2FROMMP(777p) USHORT Extracts the high-order word (16-bit
value) from message parameter 77tp.
LONGFROMMP(777p) ULONG Converts message parameter 77tp to
an unsigned long value.
CHARMSG(p771sg) * Used to extract message parameters
for the WM_CHAR message; see ex-
planation in Chapter 6.
MOUSEMSG(p777sg) Used to extract message parameters
for mouse messages; see explanation
in Chapter 6.
COMMANDMSG(p#isg) Used to extract message parameters
for the WM_COMMAND,
WM HELP, and WM SYSCOM-
MAriDmessages;see-examplein
Chapter 7.

Macros f or Preparing Window Procedure Return Values

Macro Type Purpose


MRFROMP(p) MRESULT Converts pointer p to the type for a
window procedure return value.
MRFROMSHORT(s) MRESULT Converts 16-bit value s to the type
for a window procedure return
value.
ManagingMemory 89 .

• Tlable3.2: Use i oS|2 Macros (con_t_i_PP4

M acro Type Purpose


MRFROM2SHORT(sl , s2 ) MRESULT Forms a window procedure return
value from the low-order 16-bit
value sl and the high-order 16-bit
value s2.
MRFROMLONG(J) MRESUIT Converts 32-bit value J to the type
for a window procedure return
value.

Macros f or Extracting Values Returned from Messages

Macro Type Purpose


PVOIDFROMMR(mr) PVOID Converts message return value 77zr to
an untyped pointer.
SHORTIFROMMR(77ir) USHORT Extracts the low-order word (16-bit
value) from message return value 777r.
SHORT2FROMMR(77zr) USHORT Extracts the high-order word (16-bit
value) from message return value 777r.
LONGFROMMR(7#7`) ULONG Converts a message return value to
an unsigned long type.

Although the purpose of many of these macros may seem unclear at


this point, the following chapters will clarify their use, and you can
refer back to Table 3.2 as additional macros are introduced in sub-
sequent versions of the example program.
The second procedure that the function main calls before initializing
the Presentation Manager is ReadFile (listed in Figure 3.3), which
creates a fec¢p (explained later), and then reads the file line by line into
blocks of memory dynamically allocated from this heap. The function
main passes ReadFile the name of the file, which is obtained from the
command line through argv [1].
• 90 Programmer's Guide to the os/2 Presentation Manager

int ReadFile /* Reads file into editor.


(char *FileName) /* Name of file.
(
FILE *PtrFile; /* File stream pointer.
long FileLength; /* Size of file.
USHORT Heapsize; /* Size of allocated heap.
NPCH Heapoffset; /* Offset of blocks within heap.
unsigned char LineLength; /* Length of lines.
PCH Farptr; /* Temporary far pointer.
/*** Open the file. ********************************************************„/

if ((PtrFile = fopen (FileName,"r")) == NULL)


return (ERROPEN) ;

/*** Obtain and test file length. ***************„***************************/

if ((FileLength = filelength (fileno (PtrFile))) == -1)


return (ERROPEN) ;

if (FileLength > 50000)


return (ERRTOOBIG) ;

/*** Allocate a heap to hold file lines. *************************************/

/* Make heap 20% larger than size of file.


Heapsize = (USHORT) (FileLength + FileLength / 5) ;

HHeap = WincreateHeap
(0, /* Segment address: 0 means allocate new segment.
Heapsize /* Initial heap size.
0, /* Minimum increase size: 0 means use default.
0, /* Minimum # of dedicated free lists: none.
0' /* Maximum # of dedicated free lists: none.
0); /* Options: none.
/*** Obtain selector to heap segment. ****************************************/

Farptr = WinLockHeap (HHeap) ;


Heapselector = SELECTOROF (Farptr) ;

/*** Read each line in file into a separate block allocated from heap. *******/
LastLine = -1;
while (fgets (LineBuffer,LINEBUFSIZ-1,PtrFile) != NULL)
(
/*** Test for line limit --update 'LastLine'. *********************/
if (++LastLine >= MAXLINES)
return (ERRMAXLINES) ;

/*** Calculate length of line. *************************************/


LineLength = (unsigned char)strlen (LineBuffer) + 1;/* Include null*/

/*** Insert '\n' into overlength lines. ****************************/


if (LineLength == LINEBUFSIZ - 1 &&

• Figure 3.3..
The function ReaLdFhe from the example program
ManagingMemory 91 .

LineBuffer [LINEBUFSIZ -3] !-'\n')


(
LineBuffer [LINEBUFSIZ -2] -,\n';
LineBuffer [LINEBUFSIZ -1] -,\0,;
++LineLength ;
)

/*** Allocate a block from heap to hold the line. ******************/


Heapof fset = WinAllocMem
(HHeap, /* Heap handle. */
LineLength) ; /* Length of line to store. */
if (Heapoffset == NULL)
return (ERRALLOC) ;

/*** Copy line into heap block. ************************************/


movedata (Lineselector, Lineoffset,Heapselector,
(unsigned) Heapof fset , LineLength) ;
/*** Insert line information into the table. ***********************/
LineTable [LastLine] .LineAddress = MAKEP (Heapselector,Heapoffset) ;
LineTable [LastLine] .LineLength = LineLength;
)

/*** close t:he £±Le. *********************************************************/


fclose (PtrFile) ;
return (0) ;

} /* end of ReadFile */

• Figure 3.3..
The function ReaLdHle from the example progran (continued)

ReadFile first opens the file by calling fopen. Note that ReadFile
employs the high-level file-management functions fopen, fgets, and
fclose, which are provided by the standard C library. Although these
functions may not be the most efficient means for reading the file and
extracting individual lines, they are convenient to use, are familiar to C
programmers, and permit the example code to focus on the unique fea-
tures of Presentation Manager programming. The section on Enhance-
ments, near the end of the chapter, offers some suggestions for
improving the file-handling efficiency.
Once the file is opened, ReadFile tests the length of the file by calling
the C function filelength. If the file is larger than 50,000 bytes, ReadFile
returns an error message. Therefore, 50,000 bytes is the maximum file
size that can be handled by the current version of the text editor, for
reasons that will be explained shortly. Suggestions for greatly increas-
ing this limit are discussed in the Enhancements section.
• 92 Programmer's Guide to the os/2 PresentationManager

ReadFile next calls the Presentation Manager function Wincreate-


Heap (Figure 3.4) to create a 77c¢p for storing and managing the file data.
In general, a heap is a block of memory out of which the system can
dynamically allocate smaller blocks of memory. WincreateHeap
creates and initializes a heap that is managed by the Presentation
Manager; you can allocate and free blocks of memory from this heap
using the functions that will be described in this section.
As you can see from Figure 3.4, a Presentation Manager heap can be
placed in one of two locations. First, you can create a heap within the

WincreateHeap
Purpose..
Creates and initializes a heap for dynamically allocating
blocks of memory.

Prototype..
HHEAP APIENTRY WincreateHeap
(USHORT selHeapBase, Selector of the segment to contain the
heap (the application program must
have already explicitly allocated a
segment for the heap). A value of 0
means cz.£fecr to locate the heap at the
end of the application's automatic data
segment (if the next parameter,
cbHeap, is also 0), or to allocate a new
segment for a heap (if the next
parameter is not 0).
USHORT cbHeap, J7iz.£z.¢J size of heap in bytes (note that
the system will automatically expand
the heap to fill memory requests up to
the 64-kilobyte segment limit). A value
of 0 means cz.ffecr that the heap is being
placed in the program's automatic
data segment (if the first parameter,
selHeapBase, is 0), or that the program
has already explicitly allocated a new
segment for the heap (if the first
parameter contains a selector).

• Figure 3.4..
The WincreaLteHeaLp Presentation Manager function
ManagingMemory 93 .

The following is a summary of the


effects of various combinations of the
first two parameters.

segHeapBase cbHeap Effect


Places heap at
end of program's
automatic data
segment
!=0 Allocates a new
separate segment
for the heap from
the operating
system
!=0 Program has allo-
cated a separate
segment by call-
ing DosAllocseg;
places heap
within this seg-
ment
!=0 !=0 Applies only to
dynamic-link
library modules

USHORT cbGrow, Minimum number of bytes by which


the heap must be expanded if it
requires additional memory to fulfill
a memory allocation request. A value
of 0 means to use the default amount
(512 bytes).
USHORT cbMinDed, Minimum block size to be given a
dedicated free list.
USHORT cbMaxDed, Maximum block size to be given a
dedicated free list.

• Figure 3.4..
The WincreateHeap Presentation Manager function (continued)
®94 Programmer's Guide to the OS/2 Presentation Manager

USHORT foptions) ,. Options; the only option currently


supported is HM MOVEABLE, which
specifies that the Leap should support
movable objects. A value of 0 indicates
no options.

Return Value ..
A heap handle if the heap was successfully created, and 0
otherwise.

Notes..
The cbMinDed and cbMaxDed parameters allow you to
specify a range of block sizes that will be placed on dedi-
cated free lists. A dedicated free list is a list of free blocks of a
given size; such a list allows these blocks to be allocated with
maximum efficiency.

Relate d Functions ..
WinDestroyHeap (Figure 3.5)
WinAllocMem (Figure 3.7)
WinFreeMem (Figure 3.10)

• Figure 3.4..
The WincreateHeaLp Presentation Manager function (continued)

prograLm's automatic data segment. The aLulorr\at±c (or default) data seg-
ment contains the program's initialized, uninitialized, and constant
data, as well as the program stack. (A large data model C program may
have one or more additional segments to contain data that does not fit
within the automatic segment. The size of the stack is determined by the
STACKSIZE statement in the linker definition, .DEF, file.) You can also
reserve a given number of bytes for a JocoZ heap at the end of the auto-
matic data segment through the HEAPSIZE statement in the linker
definition file; the example program reserves 1024 bytes for a local
heap. By assigning 0 to the first two parameters passed to Wincreate-
Heap (selHeapBase, the heap selector, and cbHeap, the heap size), you
cause the Presentation Manager to initialize a heap within the area at
the end of the automatic data segment that was reserved for this
ManagingMemory 95 .

purpose; the size of this heap is the size given by the HEAPSIZE state-
ment. The advantage of locating the Presentation Manager heap within
the automatic data segment is that you can efficiently address this
memory using near pointers (that is, pointers containing only the offset
portion of the address; the selector for the automatic data segment is ¢Z-
rc¢dy contained in the DS register, and therefore pointers do not have to
include the selector value).
Alternatively, you can locate the heap within an entirely separate
segment that is 71of reserved when the program is loaded, but rather is
allocated after the program begins running. By assigning 0 to the first
parameter (selHeapBase, the heap selector) and by assigning the
desired initial heap size to the second parameter (cbHeap), the example
program causes WincreateHeap to allocate a 71czu segment from the
operating system and initiahze this segment as a heap. The initial size
requested for this heap is based upon the length of the file. The ad-
vantage of placing the heap within a newly allocated data segment is
that the program need allocate only the amount of memory actually re-
quired for storing the file; if the heap were located within the automatic
data segment, you would have to reserve an arbitrary large amount of
memory through the HEAPSIZE definition file command in order to ac-
commodate various file sizes. Also, a separate segment can contain a
larger heap than the automatic data segment, which must also hold the
program's stack and data.
Note that the value passed as the second parameter to Wincreate-
Heap (cbHeap) specifies the z.71z.fz.¢J heap size; the Presentation Manager
will automatically enlarge the heap (up to the 64-kilobyte segment size
limit) if it cannot fill a given allocation request. The example program
requests an initial heap size that is 20 percent larger than the length of
the file so that the Presentation Manager need not immediately expand
the heap; this added memory will accommodate any additional infor-
mation the system must store to maintain the heap, and it will allow the
user to add data to the file. If the file size continues to grow, the Presen-
tation Manager will eventually have to call the OS/2 kernel to expand
the segment containing the heap.
Since the heap is stored within a single segment, however, it cannot
grow beyond the segment size limit of 64 kilobytes (an unfortunate con-
sequence of the segmented architecture of the 80286 processor). Conse-
quently, the program will not process a file that is longer than 50,000
• 96 Programmer's Guide tothe os/2PresentationManager

bytes (allowing for file expansion). Also, if the file size grows to the
maximum size (in later versions of the program that allow data entry),
the program will save the current contents of the file and will quit with
an error message. As mentioned in the section on Enhancements, you
can use multiple heaps to overcome this size limitation and take ad-
vantage of the large memory space afforded OS/2 applications.
The next parameter to WincreateHeap, cbGrow, specifies the mini-
mum number of bytes by which the system will expand the heap when
additional memory is required. The function ReadFile sets this
parameter to 0 to request the default amount (512 bytes). The next two
parameters, cbMinDed and cbMaxDed, specify a range of specific
block sizes that are to be managed with dedicated free lists. The system
can place a collection of free blocks that have the same size within a
dedicated list to increase the efficiency of allocating these blocks. If all of
the blocks used by a program are the same size (or if there is a narrow
range of sizes), it should request the system to use a dedicated free list
(or lists, if there is a range of sizes) for these blocks. As you will see,
however, the example program allocates separate blocks from the heap
for each line of the file; since these blocks are of random lengths, the
program assigns 0 to cbMinDed and cbMaxDed, indicating that no
dedicated lists are desired. Note that WincreateHeap returns a handle
to the heap (stored in HHeap), which must be passed to all subsequent
heap functions.
Before the application terminates (in the Quit function, described in
the next section) it calls WinDestroyHeap (Figure 3.5) to free the
memory segment containing the heap.
Although WincreateHeap returns a handle, you may have noticed
that an important value is still missing: the selector of the memory seg-
ment that contains the heap (remember that since the heap is 71of in the
automatic data segment, the program needs the selector to construct the
far pointer used to address locations within the heap). The far address
of a heap is returned by the Presentation Manager function WinLock-
Heap (Figure 3.6); the program calls this function and then extracts the
selector value and stores it in the variable Heapselector.
The function ReadFile now enters the main while loop that reads
lines from the file and inserts them into the heap. With each repetition of
the loop, the program performs the following steps:
ManagingMemory 97 .

It reads the next line from the file into the temporary buffer Line-
Buffer, by calling the C library function fgets.
It updates the variable LastLine, which contains the number of
the last line stored in the heap (and quits if the maximum num-
ber of lines, MAXLINES, is exceeded).
• It calculates the length of the line (by calling strlen) and allocates
a block of memory from the heap just large enough to contain
the line, including the newline character and the terminating
null. The block is allocated by calling the Presentation Manager
function WinAllocMem (Figure 3.7). Note that if the line is over-
sized (that is, it exceeded the maximum buffer length passed to
fgets and therefore does not contain a newline character), the
program inserts a newline.

WinDestroyHeap
Purpose..
Destroys a heap previously created by WincreateHeap.

Prototype..
HHEAP APIENTRY WinDestroyHeap
(HHEAp hHeap) ,. Heap handle, returned by a prior call to
WincreateHeap.

Return Value ..
0 if the function is successful, and a nonzero value if an error
occuITed.

Related Functions ..
WincreateHeap (Figure 3.4)

• Figure 3.5..
The W±nDestrvyHeaLp Presentation Manager function
• 98 Programmer's Guide to the os/2PresentationManager

It copies the line from the temporary buffer into the newly allo-
cated block in the heap, using the C library function movedata,
which supports intersegment data moves. Unfortunately, it is not
possible to read the data directly into the heap block, since the
length of the line must be calculated before this block is allocated.
• It places the far address of the line (constmcted using the os/2
macro MAKEP) and the length of the line into the next available
entry in the line table, LineTable.

WinLockHeap
Purpose,
Supplies the far address of the base of the segment contain-
ing the specified heap.

Prototype..
PVOID APIENTRY WinLockHeap
(HHEAp hHeap) ,. The heap handle returned by a prior call to
WincreateHeap.

Return Value ..
A far pointer to the base of the memory segment containing
the heap.

Notes..
You must call this function to obtain the selector required to
access a heap that is not located within the program's auto-
matic data segment.

Related Functions ..
WincreateHeap (Figure 3.4)

• Figure 3.6..
The WLnLoc:ldleaLp Presentation Manager function
ManagingMemory 99 .

• After the last line is safely stored in the heap, the loop exits and
the program closes the file by calling the C library function
fclose.

WinAllocMem
Purpose..
AllocatesablorkofmemoryfromaPresentationManagerheap.

Prototype..
NPBYTE APIENTRY WinAllocMem
(HHEAp hHeap, Handle to the heap returned by
WincreateHeap.
USHORT cb) ,. Size of the requested block in bytes.

Return Value ..
The offset address of the allocated block, or NULL if the
function fails.

Notes..
If the heap is currently not large enough to supply the re-
quested block, WinAllocMem attempts to enlarge the seg-
ment containing the heap. If, however, it is unable to expand
the heap, it returns NULL. Note that this function returns a
near address (offset only); to address a heap located outside
of the program's automatic data segment, you must use a far
pointer containing the heap segment selector (which can be
obtained from WinLockHeap).

Related Functions ..
WincreateHeap (Figure 3.4)
WinLockHeap (Figure 3.6)
WinFreeMem (Figure 3.10)

• Figure 3.7..
The W±nA:Iloc:Mern Presentation Manager function
• 100 Programmer's Guide to the os/2PresentationManager

It may seem costly to store each line within a separate allocated


block; as you will see, however, this method greatly facilitates display-
ing, modifying, inserting, and deleting individual lines. Also, since all
of the blocks are located within a single segment, the Presentation
Manager can allocate and free them quickly. (Allocating and freeing
separate segments requires calling the operating-system kernel, and is a
relatively slow process. The Presentation Manager needs to call the
operating system only if it must enlarge the size of the heap.)
The address and length of each line is stored in an entry in the array
LineTable, which is defined as follows:

#define MAXLINES 4096 /* Maximum number of lines */


|* Ln bNf£€r */

static struct
(
PCH LineAddress,. /* Far address of line
/* in heap.
unsigned char LineLength,. /* Length of line,
/* including \n, \0.
)
LineTable [MAXLINES] ,.

Storing the addresses in this table provides the program rapid ran-
dom access to any line in the file. Storing the line lengths eliminates the
need for the window procedure to calculate the length of a each line
that it displays (as you will see, the function used to print a line in the
window requires the line length as a parameter).
The main application obtains the address of a given line by passing
the line number to the function GetLineAddr, and obtains the length of
a line by passing the line number to GetLineLength. Both of these func-
tions simply check that the line number is within the valid range and
then return the desired value from the appropriate entry in LineTable.
Note that the main application does not have direct access to Line-
Table this encapsulation of data makes it simple to modify the data
structure used to manage the file without affecting the main program.
GetLineAddr and GetLineLength are both contained within the buffer-
management module and are listed in Figure 3.8.
ManagingMemory 101 .

Note that the number of lines that the program can accommodate is
limited by the number of elements in LineTable, which is currently set
to 4096 (MAXLINES); this is a generous number of lines, considering
that the file size is presently limited to less than 64 kilobytes. The overall
data structure used to access and manipulate the lines of the file is il-
lustrated in Figure 3.9.
Memory blocks allocated from the heap may be freed by calling Win-
FreeMem. This function is described in Figure 3.10, although it is not
used until the version of the example program presented in Chapter 6.

• HANDLING ERRORS
The basic OS/2 services (Dos, KZ7d, Vz.o, and Mow functions) use a
simple and consistent scheme for reporting errors: if the function is suc-
cessful, it returns 0; otherwise, it returns a nonzero error code. The
return values of these functions are therefore reserved for communicat-
ing the error status. (Other values are returned by assigning them to
variables, the addresses of which are passed as parameters.) Many of

SHORT GetLineLength (int Line) /* Gets length of line in buffer.


(
if (Line < 0 I I Line > LastLine)
return 0;
else
/* Extract line length from table, excluding '\n' and '\0'.
return LineTable [Line].LineLength -2;

} /* end GetLineLength */

PCH GetLineAddr (int Line) /* Gets address of buffer line. */


(
if (Line < 0 I I Line > LastLine)
return NULL;
else
return LineTable [Line] .LineAddress;

} /* end GetLineAddr */

• Figure3.8:
The functions GetLineLer\gth and GetLineAddr from the example program
• 102 Programmer's Guide to the os/2PresentationManager

the Presentation Manager functions, however, directly return informa-


tion other than the error status (for example, functions that return hand-
les). These functions must therefore indicate an error condition by
returning a spcci.¢J t7¢Jt# that is outside the normal range of return
values. Accordingly, the value returned when an error occurs depends
upon the specific Presentation Manager function, and is given in the
documentation for each function. Table 3.3 lists the special error return
values for the Presentation Manager functions used by the program
given in this chapter.
You can see from Table 3.3 that the special error return value is often,
but not always, equal to 0 (or OL). Also, unlike the basic OS/2 services,
the Presentation Manager functions do not directly supply a code in-
dicating the specific error that occurred. You can obtain this information
by calling WinGetLastError (Figure 3.11), which returns a 32-bit error

• Figure 3.9..
The data structure used to manage the file lines
ManagingMemory 103 .

code; the high-order word contains a code for the severity level, and the
low-order word contains a code indicating the specific error. You can in-
clude identifiers in your program for both of these types of errors by
defining the constant INCL_ERRORS before including OS2.H. See the
latest version of the appropriate header file (PMWIN.H for the Wz.71
functions and PMGPI.H for the Gp£. functions) for a list of the error iden-
tifiers and the corresponding codes that can be returned by the Presen-
tation Manager functions (the error code constants begin with the
prefix PMERR_).

WinFreeMem
Purpose..
Frees a memory block from a heap managed by the Presen-
tation Manager.

Prototype..
NPBYTE APIENTRY WinFreeMem
(HHEAp hHeap, Handle to the heap returned by
WincreateHeap.
NPB¥TE npMem, Offset of the memory block to be
freed, returned by a prior call to
WinAllocMem (or WinReallocMem).
USHORT cbMem) ,. The size of the block to be freed.

Return Value ..
NULL if the function is successful; otherwise, it returns the
value passed in the npMem parameter.

Related Functions ..
WincreateHeap (Figure 3.4)
WinAllocMem (Figure 3.7)

• Figure 3.10..
The W±nEreeMe" Presentation Manager function
• 104 Programmer's Guide to the os/2 PresentationManager

• Tlabl,e3.3.. S ecial Error Return Values the Presentation Mama er Functions Used in This Cha

Function Special Value Returned on Error


GpicharstringAt GPI ERROR (OL)
GpicreateLogFont FALSE(0)
GpiLoadFonts FALSE(0)
GpiQueryFonts No special value
Gpisetcharset FALSE(0)
Gpisetcolor FALSE (0)
WinAIlocMem NuL (0)
WinBeginpaint NULL (OL)
WincreateHeap NULL (OL)
WincreateMsgQueue NULL (OL)
Wincreatestdwindow NULL (OL)
WinDefwindowproc Depends upon the message
WinDestroyHeap Nonzero value
WinDestroyMsgqueue FALSE (0)
WinDestroywindow FALSE (0)
WinDispatchMsg Depends upon the message
WinEndpaint FALSE (0)
WinFillRect FALSE (0)
WinFreeMem Nonzero value (= npMem parameter)
WinGetMsg No special value
WinGetps NULL (OL)
Winlnitialize NULL (OL)
WinLockHeap NULL (OL)
WinMessageBox DID EREOR (OxFFFF)
WinQuerywindowRect FALSE (0)
WinRegisterclass FALSE (0)
WinReleaseps FALSE (0)
WinTerminate FALSE (0)
ManagingMemory 105 .

WinGetLastError
Purpose..
Returns the system error code set by the last Presentation
Manager function that failed, and resets the system error
code to 0.

Prototype..
ERRORID APIENTRY WinGetLastError
(HAD hab) ,. Anchor block handle.

Return Value ..
A 32-bit error code, containing the following values:

High-order word One of the following codes for the


general severity level:
SEVERITY NOERROR
SEVERITY WARNING
SEVERITY-ERROR
SEVERITY-SEVERE
SEVERITY-UNRECOVERABLE
Low-order word A code indicating the specific error.
These codes are listed in Appendix D
for all Wz.71 functions; for other
Presentation Manager functions,
refer to the function description in
the technical documentation.

Related Functions ..
WinGetErrorlnfo
WinFreeErrorlnfo

• Figure 3.11..
The WinGctLaLstEITor Presentation Manager f unction
• 106 Programmer's Guide to the os/2 Presentation Manager

In summary, you can handle an error condition that occurs when calling
a Presentation Manager function through the fonowing series of steps:

1. Include the constant definitions for error codes by defining


INCL_ERRORS before including OS2.H.
2. Before calling the presentation Manager function, call winGet-
LastError to reset the system error status for the current program
thread to 0.
3. Call the presentation Manager function, and test the return value.
4. If the return value equals the special error value for that func-
tion, then call WinGetLastError to obtain a code for the specific
error.
5. Branch to an appropriate error-handling routine, depending
upon the error code returned by WinGetLastError.

For example, the following code fragment handles the error condi-
tions that may occur when calling WinAllocMem.

#define INCL WIN


#define INCL-EREORS
#include <OSZ.H>

ERRORID Error,.
NPCH Heapoffset ,.

Heapoffset = WinAllocMem (HHeap, LineLength) ,.


if (Heapoffset == NULL)
(
Error = WinGetLastError (IIAncBlk) ;
switch (LOUSHORT (Error) )
(
case PRERR HEAP OUT 0F REMORY:
/* ENarrng-e treEi-@ or;k o-i rne!"ory error . * /

case PRERR HEAP MAX SIZE REACHED:


/* Manage heap rea-ched-maximum size error. */
ManagingMemory 107 .

default :
/* Manage any other heap-allocation error. */
)
)

Note that you can also call the Presentation Manager functions Win-
GetErrorlnfo and WinFreeErrorlnfo to obtain more detailed error in-
formation. See the Presentation Manager technical documentation for
information on these two functions.
To simplify the code, the example programs presented in this book
perform only minimal error checking. Correct programming should
eliminate most errors; some errors, however, cannot easily be
prevented. For example, if the user enters more data into the file than
can be held within the single segment used to contain the heap, the
function WinAllocMem returns the special value NULL to indicate that
the maximum heap size has been reached. In this case, the function
ReadFile simply returns the value ERRALLCX= indicating a general
memory-allocation failure, without calling WinLastError to determine
the specific error (if WinLastError were called, it would return the value
PMERE HEAP MAX SIZE REACHED). Note that ERRORALLOC is
one of a set of Elrror codes that can be returned by the buffer-manage-
ment module; these codes are defined at the top of the example pro-
gram and are listed in Figure 3.1. The buffer-management module also
provides a function, ErrorMessage (listed in Figure 3.12), that returns
the string corresponding to a given error code.
When the main part of the example program encounters a fatal error,
it calls the utility function ErrorQuit (listed in Figure 3.13), passing it an
error message. ErrorQuit formats the message and then cans Win-
MessageBox (Figure 3.14) to display the message. It then terminates the
program by calling the function Quit (also listed in Figure 3.13). Note
that both the functions main and ErrorQuit terminate the program by
calling Quit, which releases the heap and performs the other final tasks
required of a Presentation Manager program that were explained in
Chapter 2.
The function WinMessageBox displays a message box, which is a
temporary window containing a specified title and message, and one of
four standard icons. The message box also contains one or more p#sfe
Z7##o7is (explained in Chapter 8) that you specify when you call this
• 108 Programmer's Guide to the os/2 Presentation Manager

function. When the user selects a push button, WinMessageBox


removes the temporary window and returns control to the calling pro-
gram. The message box created by ErrorQuit displays the name of the
program as the title (the fourth parameter, pszcaption) and prints
the error message as the text inside the box (the third parameter, psz-
Text). The box also contains an icon in the shape of a hand (recom-
mended for serious errors, and specified through the sixth parameter,
flstyle) and a single push button labeled Ok (also specified through the
flstyle parameter). When the user presses the Spacebar or Enter key, or
clicks the mouse with the pointer inside the push button, the message
box is removed and control returns to ErrorQuit. This message box is
illustrated in Figure 3.15.
Note that the first parameter passed to WinMessageBox (hwnd-
Parent) is the handle of the owner of the message box window; the ex-
ample program specifies the desktop window (HWND_DESKTOP).
Accordingly, the message box is a top-level window and is 71of confined
to the area of the frame window, but can be placed anywhere on the
screen. (You do not control the initial placement or size of this window;
the system automatically centers it in the screen and makes it large
enough to accommodate the message text.)

char *ErrorMessage /* Returns a string that describes an error code. */


(int ErrorNumber) /* The error code.
(
static char *MessageTable [] =
(
''no error",
''file open failure",
''file too large",
''maximum lines exceeded",
"heap memory allocation failed",
"unidentified error"
);

if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))


ErrorNumber = sizeof (MessageTable) / sizeof (char *) -1;
return MessageTable [ErrorNumber] ;

) /* end ErrorMessage. */

• Figure 3.12..
The function EITorMessaL8e from the example program
ManagingMemory 109 .

The second parameter, hwndowner, gives the ozu71cr of the message


window. The owner of a window is distinct from the p¢rc7if of the win-
dow (which was explained in Chapter 2). Unlike the parent-child
relationship, a window is not confined to the area occupied by its
owner, and it is not automatically destroyed when its owner is de-
stroyed. The owner-owned relationship is optional; a window does not
need to have an owner, and you can change the owner of a window
through the function Winsetowner. In general, a control window (such
as a scroll bar, discussed in Chapter 4) sends a message to its owner
when it receives input from the user. The owner specified through the

void ErrorQuit /* Terminate program due to fatal error condition.


(char *Message) /* Error message to display to user.
(
char Buffer [60];

sprintf (Buffer,"Program Error: %s",Message) ;

WinMessageBox /* Display a message box.


(HWND DESKTOP, /* Handle of parent: desktop window.
HF`rame , /* Handle of owner: frame window.
Buffer, /* Message text.
''PM Text Editor", /* Caption.
0, /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB ICONHAND) ; /* Display a hand icon.
Quit (1); /* Call normal termination function.
} /* end ErrorQuit */

void Quit
(int Errorcode) /* Process termination status.
Calls Presentation Manager termination functions and ends program
with specified error code.
(
if (HHeap != NULL)
WinDestroyHeap (HHeap) ;
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue) ;
WinTerminate (HAncBlk) ;
exit (Errorcode) ;
) /* end Quit */

• Figure 3.13..
The functions EITorQuft and Quit from the example program
• 110 Programmer's Guide to the os/2 Presentation Manager

WinMessageBox
Purpose..
Displays a message box window.

Prototype..
USHORT APIENTRY WinMessageBox
(HWND hwndparent , The parent of the message box
window (HWND DESKTOP if the
message box is to-be a top-level
window).
Hve hwndovner, The owner of the message box
window; this window is activated
when WinMessageBox returns.
PSZ pszText, Address of the null-terminated string
to be displayed within the message
box; you can insert carriage-return
characters within this string to display
multiple lines.
PSZ pszcaption, Address of a null-terminated string to
be displayed as the title of the message
box; if this parameter is NULL, the
default title fr7`or is displayed.
USHORT idwindow, The window ID of the message box
window; if no ID is required, you can
set this parameter to 0.
USHORT flstyle) ,. The message box style; you can specify
one or more of the following style
values (they should be combined
using the I operator):
Style Effect
MBOK Include push
button labeled
Ok
MB OKCANCEL Include Ok and
C¢71ccJ push but-
tons
MB RETRYCANCEL Include Rcfny
and Cfl77ccJ push
buttons

• Figure 3.14..
The WLn:MessaLgeBox Presentation Manager f unction
ManagingMemory 111 .

MB ABORTRETRY- Include AZ7or£,


IGN_ORE Retry , aLnd Ignore
push buttons
MB YESNO Include Yes and
No push buttons
MB YESNOCANCEL Include yes, No,
and C¢#ccJ push
buttons
MB HELP Include a HCJp
push button
MB ICONHAND Include a hand
icon; recom-
mended for
serious errors
MB ICONQUESTTON Include a ques-
tion mark icon;
recommended
to warn and
elicit response
from user
MB ICON- Include an ex-
EXELAMATION clamation mark
icon; recom-
mended for
warnings
MB ICONASTERISK Indude an
asterisk icon;
recorrmended
for reporting
status information
MB DEFBurTONi First button is
default (that is,
selected through
the Enter key)
MB DEFBUTTON2 Second button is
default
MB DEFBUTTON3 Third button is
default

• Figure 3.14..
The W"essaLgeBox Presentation Manager function (continued)
• 112 Programmer's Guide to the os/2PresentationManager

MB APPLMODAL The message box


is application
modal (user can-
not switch
to another win-
dow in ourrent
application)
MB SYSTEMMODAL The message box
is system modal
(user cannot
switch to other
applications)

Return Value ..
One of the following values, indicating which button the
user selected or an error status:

Return Value Meaning


DID ERROR An error occurred
MBID ABORT AZ7o7'£ button was selected
MBID CANCEL C¢71ccZ button was selected, or Esc
was pressed
MBID IGNORE Jg77orc button was selected
MBID NO No button was selected
MBID OK Ok button was selected
MBID RETRY Rcf ny button was selected
MBID YES Yes button was selected

• Figure 3.14..
The W±n:MessageBox Presentation Manager function (continued)

hwndowner parameter is the window that becomes active when Win-


MessageBox returns (the notion of an active window is also discussed
in Chapter 4). The example program specifies the frame window
(HFrame) as the owner of the message box.
Note also that since the frame window is specified as the owner of
the message box window, you cannot call WinMessageBox until after
ManagingM¢mory 113 .

PM Text Editor
: © ::°mg::in Error: Must specify fi|e

:cE

• Figure 3.15..
The message box displayed by the example progran

the frame window has been created though the call to Wincreatestd-
Window. The example program, however, must call ReadFile Z7c/ore
creating the window (remember that creating the window causes the
WM_PAINT message to be sent to the window procedure, which dis-
plays file data from the buffer). Accordingly, the function main retains
the error code returned from ReadFile, and then tests; this code-pos-
sibly calling ErrorQuit-after the call to Wincreatestdwindow.

• DISPLAYING TEXT
The version of the example program presented in Chapter 2 simp-
ly displayed a string that was justified at the upper left corner of the
client window. This version illustrated the concept df cc71fr¢Zz.zt.71g all
code for drawing window data within a single routine, which is in-
voked whenever an event external to the program requires that data be
redrawn, or whenever the program itself needs to modify the display.
The version of the example program presented in the present chapter
prints as many lines from the beginning of the file as Will fit within the
• 114 Programmer's Guide to the os/2 Presentation Manager

client window. This program illustrates two more concepts important


for displaying data within a Presentation Manager window:

• Keeping the appearance of`the display independent of the resolu-


tion of the display device
• Adjusting the display for the current size of the window

To achieve these two objectives, the window procedure belonging to


the current version of the example program needs to process three mes-
sages: WM_CREATE, WM_SIZE, and WM_PAINT (the previous ver-
sion processed only the WM_PAINT message). As in the previous
version, all other messages are passed to the function WinDefwindow-
Proc for default processing.

The WM_CREATE Message


The WM_CREATE message (Figure 3.16) is sent to the window procer
dure immediately after the window is created but before it becomes visible;
thismessageanowsthewindowproceduretoperformrequiredinitialization
tasks. In the example program, the WM_CREATE message is processed by
the function Create (listed in Figure 3.17), which loads the required charac-
ter font and stores the dimensions and other attributes of this font. As you
will see in the explanation of the WM_PAINT message, the font loaded by
Create is used to display the file data within the window.
The function Create first calls GpiLoadFonts (Figure 3.18) to load the
set of Courier fonts from the font file COURIER.FON. (Note that you
must specify the full path name for this file.)
The Courier font style is selected because it is the only standard font
style supplied with the Presentation Manager that consists of fixed-
width characters. Since all characters have the same width, they are
aligned in vertical columns, which is the appropriate style for writing
programs and other text files. (Also, using fixed-width characters great-
ly simplifies the logic for positioning the cursor and manipulating the
data on the screen.) The other loadable fonts, as well as the default sys-
tem font, contain proporfl.o77¢Jzy sp¢ccd characters. With these fonts, char-
acters do not occupy the same width; rather, narrow characters such as
1 are contained in a smaller horizontal space than wide characters such
as W. Note that the example program in Chapter 2 (Figure 2.27) simply
ManagingMemory 115 .

used the default system font; also, the system displays titles, menu
labels, and other textual data using the default font. Therefore, these
items all appear with proportionally spaced characters.
The function Create next calls WinGetps (Figure 3.19) to obtain a
handle to a presentation space. WinGetps supplies a cache presenta-
tion space, which was explained in Chapter 2. This function is called be+
cause the next function invoked (GpiQueryFonts) requires a
presentation space handle.
Once the program has obtained a presentation space, it calls Gpi-
QueryFonts (Figure 3.20) to obtain detailed information on a selected
font. Note that a given font file typically contains several distinct fonts;
once the font file is loaded, au of the fonts it contains are available to the

WM CREATE
Purpose..
Sent by the system to a window when it is first created. It
allows the window procedure to perform initializations.

Parameters..
REARAM mpl Address of control data that was passed to
the function Wincreatewindow.
I@ARAM mp2 Address of a CREATESTRUCT stmcture
containing information on the window that
is being created.

Return Value ..
Return FALSE to continue window creation.

Notes..
This message is sent after the window is created but before it
becomes visible.

• Figure 3.16..
The WM_CREATE Presentation Manager message
• 116 Programmer's Guide to the os/2 Presentation Manager

program. These fonts generally conform to a common basic style (such


as the Courier style in COURIER.FON), but differ in the size of the let-
ters; the file may also include fonts that provide variations on the basic
style, such as boldface or italic letters.

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace; /* Presentation space handle.
FONTMETRICS Metrics; /* Structure to hold font dimensions.
LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts

/*** Load Courier mono-space font. *******************************************/


GpiLoadFonts
(HAncBlk, /* Anchor block handle. */
"\\OS2\\DLL\\COURIER.FON") ; /* Full path name of font file. */

/*** Obtain a handle to a presentation space. ********************************/


Hpresspace = WinGetps (hwnd) ;

/*** Obtain information on Courier font. *************************************/


GpiQueryFonts
(Hpresspace, /* Handle to presentation space.
QF_PRIVATE, /* Enumerate private fonts.
"Courier", /* Font face name.
&Numberstructs, /* Number of FONTMETRICS structures returned.
(long)sizeof (FONTMETRICS) ,/* Length of structure for EACH font.
&Metrics) ; /* Address of FONTMETRICS structure(s).

/*** Store font information in global variables. *****************************/


ycharTot = (SHORT)Metrics. IMaxBaselineExt;
ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (FontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes. IMatch = Metrics. IMatch;
strcpy (FontAttributes. szFacename,Metrics. szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes.1Avecharwidth = Metrics. IAvecharwidth ;
FontAttributes. fsType = FATTR TYPE FIXED;
FontAttributes. fsFontuse = 0;
/*** Release presentation space. *********************************************/
WinReleaseps (Hpresspace) ;
return FALSE;

} /* end Create */

• Figure 3.17..
The function Create from the exanple program
ManagingMemory 117 .

A single call to the function GpiQueryFonts can supply information


on any number of fonts that have been loaded (from one or more font
files), as well as information on the default system font. Tfie function
Create, however, requests information only on the first available
Courier font. This font is specified by passing the string ``Courier" as
the third parameter, which supplies the face name of the font; also, the
variable pointed to by the fourth parameter is assigned a value of 1,
which requests information on only a sz.7zgJc font. Accordingly, Gpi-
QueryFonts returns information on the first available font that matches
the face name Courier.
(As a program enhancement, you could read information on all
available Courier fonts, and then select-or allow the user to select-
the most appropriate font. Note that the function GpiQueryFonts

GpiLoadFonts
Purpose..
Loads one or more fonts from a font file.

Prototype..
BOOL APIENTRY GpiLoadFonts
(HAD hab, Anchor block handle.
pSz pszFilename) ,. A NULL-terminated string containing
the full path name of the file
containing the definition of the fonts to
be loaded (the file has the .FON
extension).

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Relate d Function..
GpiQueryFonts (Figure 3.20)

• Figure 3.18..
The GPILoaLdEor\ts Presentation Manager function
• 118 Programmer's Guide to the os/2 Presentation Manager

returns the number of remaining fonts for which information has 7zof
been read, thus allowing you to determine the total number of fonts
available that match the specified face name. You could dynamically al-
locate a temporary block of memory from the operating system to hold
the font information.)
The information supplied by GpiQueryFonts is received in the fields
of one or more FONTMETRICS structures (defined in OS2DEF.H). Since
the example program requests information on only a single font, it allo-
cates and passes the address of a single FONTMETRICS structure
(Metrics). The program uses the font information obtained from Gpi-
QueryFonts for two basic purposes.

WinGetps
Purpose..
Obtains a cache presentation space.

Prototype..
EPS APIENTRY WinGetps
(HWND hwnd) ,. Handle of the window to obtain a
presentation space.

Return Value ..
The handle of the presentation space; returns NULL if an
error occurs.

Notes..
The presentation space must be released by calling Win-
Releaseps.

RelatedFunctions..
WinReleaseps (Figure 3.22)

• Figure 3.19:
The WinGctps Presentation Manager function
ManagingMemory 119 .

GpiQueryFonts
Purpose..
Returns information on one or more of the fonts that are cur-
rently available.

Prototype..
LONG APIENTRY GpiQueryFonts
(EPS hps, Presentation space handle.
UI.ONG floptions , A flag indicating the type of
fonts to be queried; you can
pass one or both of the
fonowing values (combined
with the I operator):
Value Type of Font
QF_PUBLIC System font
QF_PRIVATE Fonts loaded by the
application ®y caning
GpiLoadFonts)

PSZ pszFacename, A string containing the font face


name (such as ``Courier'' or
``Courier Italic'' ); information
win be retrieved only for fonts
that match this name. Passing
the value NULL causes the
system to return information for
all fonts, regardless of their face
names.
PLONG pcFonts , Points to a LONG variable
containing the number of fonts
for which information is to be
retrieved.
LONG cbMetrics, Specifies the length of the
structure to receive the
information for c¢cfe font; to
receive all available
information, this value should
be sizeof (FONTMETRICS);
no more data are suppHed for
each font than the value
specified by this parameter.

• Figure 3.20..
The GPLQueryForits Presentation Manager function
•120 Programmer's Guide to the OS/2 Presentation Manager

PFONTMETRICs pfrnMetrics ) ,. Points to the FONTMETRICS


structure(s) to receive the font
information (this structure is
defined in OS2DEF.H); the
total size of the receiving buffer
must be the value of *pcFonts
multiphied by cbMetrics.

Return Value ..
The number of matching fonts for which information was
71of returned. A return value of zero indicates that informa-
tion was supplied for flJJ matching fonts (it does not indicate
an error); a nonzero value indicates that you can obtain in-
formation on additional fonts by passing a larger value in the
pcFonts parameter.

Notes..
By examining the data returned by this function, you can
choose the font most suitable for the application. To select
the desired font, you must call the functions GpicreateLog-
Font and Gpisetcharset.

Related Functions ..
GpiLoadFonts (Figure 3.18)
GpicreateLogFont (Figure 3.26)
Gpisetcharset (Figure 3.27)

• Figure 3.20..
The GPTQueryF ouls Presentation Manager function (continued)

First, it saves the value for the total character height (supplied in the
lMaxBaselineExt field of Metrics) in the global program variable
ycharTot, and the value for the height of the character descenders (sup-
plied in the lMaxDescender field) in the variable ycharDesc. These
dimensions will be used each time the WM_PAINT message is received
by the client window, and they are illustrated in Figure 3.21. Note that
in the example program, these dimensions are given in screen pixels. By
employing the actual dimensions used to display the font on the current
ManagingMemory 121 .

display device, the routine that processes the WM_PAINT message can
properly position the lines of text within the window and can maintain
a consistent screen appearance regardless of the current graphics
resolution.
Second, the function Create uses the font information it has obtained
from GpiQueryFonts to assign appropriate values to the fields of a
FATTR structure (FontAttributes) . As you will see in the section describ-
ing the WM_PAINT message, the FATTR structure is used to specify the
current font that is to be employed for displaying characters. Note that

• Figure 3.21..
The character dimensions obtained from Gp±QueryForrfe
• 122 Programmer's Guide to the os/2 Presentation Manager

since the font-management functions GpiLoadFonts and GpiQuery-


Fonts need be caued only once, they are placed in the WM_CREATE
routine, which is invoked a single time during window initialization.
The information stored from the call to GpiQueryFonts remains vahd
during the entire program. The other two font-management functions
used in the program (GpicreateLogFont and Gpisetcharset) must be
called each time a presentation space is obtained for updating the win-
dow. These functions are thus placed in the function that processes
WM_CHAR messages (Paint, described later in the chapter).
Finally, since a cache presentation space must be released before the
program returns from processing the WM_CREATE message, Create
calls the Presentation Manager function WinReleaseps (Figure 3.22)
immediately before returning, to release the presentation space
provided by WinGetps.

WinReleaseps
Purpose..
Releases the presentation space obtained though WinGetps.

Prototype..
BOOL APIENTRY WinReleaseps
(Hps hps) ,. Handle of the presentation space returned
by WinGetps.

Return Value ..
TRUE if the function is successful, and FALSE if an error
occurred.

Relate d Functions ..
WinGetps (Figure 3.19)

• Figure 3.22..
The WLnRcteaseps Presentation Manager function
ManagingMemory 123 .

The WM_SIZE Message


The system sends the WM_SIZE message (Figure 3.23) to the
client window procedure immediately after the window is created (¢cr
the WM_CREATE message), and subsequently each time the window
changes size. The example program takes advantage of this message to
maintain a record of the current vertical dimension of the client win-
dow. The WM_SIZE message is processed by the function Size, listed in
Figure 3.24. This function extracts the current vertical dimension of the
client window from the high-order word of the mp2 parameter and
stores it in the variable ywin. Note that this dimension, like the font
dimensions collected during window initialization, is also given in
screen pixel units. The vertical window dimension will subsequently be
used by the routine that processes the WM_PAINT message. This value

WM SIZE
Purpose..
Sent by the system to a window whenever its size changes.

Parameters..
REA- mpl
low-order word: Previous width.
high-order word: Previous height.
REAFLEN mp2
low-order word: Current width.
high-order word: Current height.

Return Value ..
FALSE.

• Figure 3.23..
The WM_SIZE Presentation Manager message
• 124 Programmer's Guide to the os/2PresentationManager

will be used in conjunction with the font dimensions to calculate the


number of lines that can be displayed within the window and the cor-
rect placement of these lines. (Note that when the window is increased
in size, thereby invalidating a section of screen data, the WM_SIZE mes-
sage is sent Z7c/ore the WM_PAINT message.)

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** Obtain vertical dimension of client window. ****************************/
ywin = SHORT2FROMMP (mp2) ;

return FALSE;

)/ * end Size */

• Figure 3.24..
The size function of the example program

The WM_PAINT Message


As explained in Chapter 2, the WM_PAINT message (Figure 2.19)
is sent to the client window procedure whenever any portion of the
window data becomes invalid and requires repainting. This message is
also sent by Wincreatestdwindow when the window is first created.
In review, the following three messages processed by the example pro-
gram are sent during window creation, in the order listed:

1. WM CREATE
2. WM SIZE
3. WM PAINT

The WM_PAINT message is processed by the function Paint, listed in


Figure 3.25. Like the previous version of the example program, the cur-
rent version calls WinBeginpaint and WinEndpaint to obtain and
release a presentation space. Once the current version has obtained
a presentation space, however, it calls two Presentation Manager
ManagingMemory 125 .

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window coordinates, in pixels.
SHORT StopLine; /* Last line to paint.
POINTL Start; /* Starting position to print string.
SHORT LineLength; /* Length of each line displayed.
Hpresspace = WinBeginpaint
(hwnd, /* Window handle.
0, /* Handle of PS to have clipping region set. */
0) ; /* Address of variable to set to update region.*/

/*** Create a logical font for this presentation space. **********************/


GpicreateLogFont
( Hpresspace , /* Presentation space handle.
( PSTR8 ) NULL , /* Logical font name: none.
ID COURIER, /* Local font ID.
&F6ntAttributes) /* Struct. specifying font from GpiQueryFonts.
/*** Make the logical font the current character set. ************************/
Gpisetcharset
( Hpresspace , /* Presentation space handle.
ID COURIER) ; /* Local font ID.
WinQuerywindowRect /* Get dimensions of window.
( hwnd , /* Window handle.
&Rect) ; /* Structure to receive coordinates.
WinF i I lRect /* Erase window.
( Hpresspace , /* Presentation space handle.
&Rect , /* Structure containing window coordinates.
CLR WHITE) ; /* Color to use (white) .

/*** Set foreground color used by 'GpicharstringAt'. *************************/


Gpisetcolor
(Hpresspace, /* Presentation space handle. */
CljR BIjACK); /* Color to use: black. */

/*** Calculate last line to fit in client window. ****************************/


StopLine = min (LastLine, ywin / ycharTot) ;

/*** Print lines from beginning of file within client window. ****i************/
Start.x -0;
for (Line = 0, Start.y = ywin -ycharTot + ycharDesc; Line <= StopLine;
++Line, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue ;
GpicharstringAt /* Prints string at given position.
(Hpresspace, /* Presentation space handle.

• Figure 3®25..
The function Pa;ir\+ of the example program
• 126 Programmer's Guide to the os/2 PresentationManager

:::::fiineLength, /: S:::::u:: :::::::::: ::a;::::.position.:


GetLineAddr (Line)) ;/* Address of line
)

WinEndpaint (Hpresspace) ;

return FALSE;

) /* end Paint */

• Figure 3.25..
The f unction Pal:irit of the example program (continued)

font-management functions that cause the system to use the Courier


font loaded by the Create function rather than the proportionally
spaced default system font.
First, Paint calls the GpicreateLogFont function (Figure 3.26), which
informs the system which font the program is going to use. This func-
tion creates what is termed a Jogz.c¢J /o7if dc/!.713.£€.o71. The specified font
must be either the default system font or a font that has been previously
loaded by GpiLoadFonts. The program specifies the desired Courier
font by passing as the fourth parameter the address of the FATTR struc-
ture (&FontAttributes) that was previously assigned values in the Cre-
ate function. The program also passes an identifier (the value
ID_COURIER, defined within the program), which will be used in the
next function call (to Gpisetcharset) to refer to the logical font that has
been defined.
Second, the program calls the Gpisetcharset function (Figure 3.27)
to cause the system to begin tJs£.77g the logical font defined by the call to
GpicreateLogFont. The program specifies the desired logical font by
passing the s¢777c identifier (ID_COURIER) that it passed to Gpicreate-
LogFont. Once the program has called Gpisetcharset, all subsequent
character output will use the newly defined font, until the presentation
space is released. (Note that the new font is employed only for the cur-
rent presentation space, the handle of which was passed as the first
parameter to both GpicreateLogFont and Gpisetcharset.)
Once the appropriate font has been estabhshed, the Paint function
erases the contents of the window using the functions WinQuery-
WindowRect and WinFillRect. Since the current version of the example
program needs to fill the window with evenly spaced lines from the ffle, it
ManagingMemory 127 .

GpicreateLogFont
Puxpose..
Creates a logical definition of a font.

Prototype..
BOOL APIENTRY GpicreateLogFont
(Hps hps, Handle of the presentation space for which
the font is to be defined.
PSTR8 pchName, Pointer to a logical font name, which can be
used to identify the logical font; you can
assign any name consisting of up to eight
characters.
LONG laid, The value that will be used to identify the
logical font; you can supply a value between
1 and 254; the value must not already refer
to a font or bitmap; when your subsequently
call Gpisetcharset to cause the system to
use the font, you must pass this s¢77tc value
(as the second parameter).
pFATTRs pfat) ,. Pointer to a FATRS structure (defined in
OS2DEF.H) that defines the attributes of the
logical font that is to be created; note that if
there is no font that matches the attributes
exactly, the system uses the font, of those
available, that most closely matches the
requirements; you can obtain: the attributes
for any avaiable font by calling
GpiQueryFonts.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

• Figure 3.26..
The Gp±CreateLo8Eorit Presentation Manager function
• 128 Programmer's Guide to the os/2PresentationManager

Notes..
To define a logical font using this function, the font must al-
ready have been loaded from a font file (by calling GpiLoad-
Fonts). Alternatively, if the face name in the FATTR structure
pointed to by pfat is NULL, and all of the attributes except
the code page are set to zero, the system default font is
selected in the specified code page. After calling Gpicreate-
LogFont, you must call Gpisetcharset to force the system to
start L/sz.71g the font.

Related Functions
GpiLoadFonts (Figure 3.18)
GpiQueryFonts (Figure 3.20)
Gpisetcharset (Figure 3.27)

• Figure 3.26..
The GplcreateLogForit Presentation Manager function (continued)

displays each hne using the function GpicharstringAt (Figure 3.28),


which allows you to print a line at specific position within the window.
(WinDrawText, used in the previous version, justifies text within a given
rectangle, but does not place the text at an absolute location.)
Before calling GpicharstringAt to display the file lines, however, the
function Paint performs several preliminary tasks. First, it calls Gpiset-
Color (Figure 3.29) to set the color that GpicharstringAt uses to draw
the text. The program specifies the color black (CLR_BLACK) to provide
an optimal contrast to the white background created by WinFillRect.
Second, the function Paint uses the data maintained by the other two
message-handling routines to calculate the number of lines that can be
displayed within the window and the starting position for the first line
of text. The number of lines to be displayed (StopLine) is calculated
using the following expression:

StopLine = min (LastLine, ywin / ycharTot) ,.

The macro min is defined in the C header file STDLIB.H. Since ywin is
the total number of vertical pixels in the window, and ycharTot is the
ManagingMemory 129 .

Gpisetcharset
Purpose..
Sets the current character set used for displaying textual data
within the specified presentation space.

Prototype..
BOOL APIENTRY Gpisetcharset
(Hps hps, Handle of the presentation space for which
the character set is to be set.
LONG lcid) ,. The identifier for the character set, which
can be one of the following values:

Identifier Meaning
LCID DEFAULT The default character
set (you can use this
option to restore the
default font after
temporarily using a
locally loaded font)
1 to 254 A logical font defined
by GpicreateLogFont;
you must pass the s¢777c
identifier within this
range that was passed
to GpicreateLogfont
(in the third parameter)

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Relate d Functions ..
GpicreateLogFont (Figure 3.26)

• Figure 3.27..
The GplsetchaLrset Presentation Manager function
• 130 Programmer's Guide to the os/2 PresentationManager

GpicharstringAt
Purpose..
Draws a line of text at a specified starting position.

Prototype..
LONG APIENTRY GpicharstringAt
(HPS hps, Handle of the presentation space.
PPOINTL pptlstart, Pointer to a POINTL structure (defined
below) containing the starting position.
LONG cchstring, Number of characters in the string to
be displayed.
PCH pchstring) ,. Address of character string to be
displayed.

Structure..
typedef struct POINTL
(
LONG x,.
LONG y,.
I
POINTL,.

Return Value ..
Returns a nonzero value if the function is successful, and
GPI ERROR if an error occurs.

Notes..
This function is equivalent to calling these two functions:
GpiMove (hps, pptlstart)
Gpicharstring (hps, cchstring, pchstring)
When the function has completed drawing the string, it
moves the current pointer to the end of the string.

RelatedFunctions..
GpiMove (Figure 11.22)
Gpicharstring

• Figure 3.28..
The Gp±CharstringALt Presentation Manager function
ManagingMemory 131 .

total number of vertical pixels required for a single line of text, Stop-
Line is assigned the total number of co777pJcfc lines (integer division
truncates a partial line) that fit within the window, or the value Last-
Line if the file does not contain sufficient lines to fill the window.
GpicharstringAt must be passed the address of a POINTL structure
(defined in Figure 3.28) specifying the starting point of the line of text.
Positions within a window are specified according to a coordinate sys-
tem that has its origin at the lower left corner of the window. Accord-
ingly, the point (x=0, y=0) represents the lower-leftmost pixel in the
window, and coordinates increase moving up and to the right. This
coordinate system is illustrated in Figure 3.30 (the value xwin is the
horizontal size of the window that is also supplied by the WM_SIZE
message, but is not used until Chapter 4). GpicharstringAt places the
lower left pixel-on the baseline-of the first character in the string at
the specified starting point (this position is illustrated in Figure 3.21).

Gpisetcolor
Purpose..
Sets the foreground color used by Gpz. functions such as Gpi-
CharstringAt.

Prototype..
BOOL APIENTRY Gpisetcolor
(Hps hps, Handle of the presentation space.
LONG IColor) ,. The color; you can select any of the color
values listed in Figure 2.23 (the description
of WinFillRect).

Return Value ..
TRUE if the function is successful, FALSE if an error occurs.

• Figure 3.29..
The GPTsetcofor Presentation Manager function
• 132 Programmer's Guide to the os/2 Presentation Manager

The program calculates the starting point of the first line using the
following expressions :

Start.x = 0,.
Start.y = ywin -ycharTot + ycharDesc,.

These expressions place the first line at the top of the window and jus-
tify the string at the left window edge. Finally, the vertical starting point
is decremented after each line is displayed using the following expres-
sion within the for statement:

Start.y -= ycharTot,.

This expression places each subsequent line from the file on the next
lower line position within the window.
The GpicharstringAt function is passed the length of each line. If a
line is longer than will fit within the window, the Presentation Manager
automatically clips the portion that falls outside the current window
dimensions (that is, the inappropriate points do not cause an error but
are simply not displayed). In general, when calling Presentation
Manager display functions, you can safely specify coordinates outside

• Figure 3.30..
The coordinate system used for specifying points within a window
ManagingMemory 133 .

the dimensions of the window; only the portions of a figure within the
window (if any) will be visible.
You may also have noticed that the for loop seemingly attempts to
print one more line than will fit within the window (Line ranges from 0
up to and including StopLine). Remember, however, that StopLine is
the number of co777pJcfc lines that can fit within the window. By printing
StopLine + 1 lines, the portion of any partial line that falls within the
window will be displayed; the section of this partial line that falls out-
side of the window is clipped.
Note that the current display routine always repaints the entire win-
dow. More accurately, the program only ¢ffc777pfs to repaint the entire
screen; actually, the presentation space provided by WinBeginpaint
automatically clips all data outside the current invalid window region;
ineffectual calls to GpicharstringAt, however, waste time. The pro-
gram in Chapter 4 enhances the efficiency of the display routine by
redrawing only the invalid section of the client window.

• ENHANCEMENTS
This section offers several suggestions for enhancing the version
of the example program presented in this chapter. These enhancements
are beyond the scope of the book, and are not developed in subsequent
chapters. You can use them as exercises in Presentation Manager
programming and to increase the usefulness of the example program.
First, one of the major limitations of the example program is the
restriction on file size. You cannot load a file that is larger than 50,000
bytes, and you cannot increase the file size beyond the maximum heap
size (the segment containing the heap has a maximum size of 64
kilobytes). To overcome this limitation and yet continue to use the
Presentation Manager memory-allocation functions, your program can
manage more than one heap. The following are some, suggested steps
for greatly increasing the maximum file size by using multiple heaps:

1. Create an initial heap (WincreateHeap) and begin allocating


memory (WinAllocMem) within this heap for all lines loaded
from the file or inserted by the user (inserting lines is discussed
in later chapters).
• 134 Programmer's Guide to the os/2 Presentation Manager

2. When winAllocMem returns NULL and winGetLastError


returns PMERE_HEAP_MAX_SIZE_REACHED, indicating that
the maximum heap size has been attained, create another heap
(WincreateHeap) and begin allocating from the new heap. Since
LineTable contains the complete far address of each line, the fact
that lines are contained in multiple heaps is invisible to the pro-
gram. Repeat this step as necessary.
3. As you will see in subsequent chapters, when the user adds or
deletes data, you must deallocate the memory block containing
the current line by calling WinFreeMem. This function requires
the handle to the appropriate heap. The selector of the far ad-
dress contained in LineTable can be used to uniquely identify
the specific heap (each heap has a unique segment selector). You
can find the corresponding heap handle in a lookup table you
maintain, which contains selector/handle pairs.

Note that as memory blocks are allocated and deallocated, the pro-
gram should limit the number of partially filled heaps. Alternatively,
you could possibly attain greater efficiency by completely bypassing
the Presentation Manager heap functions, and writing your own heap-
management routines; the raw memory for your heap could be ob-
tained directly from the operating system through the DosAllocHuge
function, which allocates blocks of memory consisting of more than one
segment.
As a second possible enhancement to the example program, you
could increase the efficiency of the routine that reads data from the file
and extracts individual lines. For simplicity, this routine calls the stand-
ard high-level C function fgets to extract each line from the file. Altema-
tively, you could read the entire file (or 64-kilobyte blocks of the file, if
the file is longer than this size) directly into a temporary buffer. You can
dynamically allocate this buffer from the operating system though the
DosAllocseg OS/2 function, and you can read the file directly into the
buffer with a single call to the DosRead system routine (you must open
and close the file using Dosopen and Dosclose). You can then write
your own routine to efficiently extract individual lines and copy them
into the heap. (If you have written your own heap-management
module, you may even be able to leave the lines in the buffer into which
they were initially read, eliminating the copy operations!)
ManagingMemory 135 .

• CONCLUSION
The MAKE file for preparing the current version of the example
program is provided in Figure 3.31, the definition file is given in Figure
3.32, and the complete program listing is in Figure 3.33.
This chapter has introduced the basic data structures and routines for
reading the file and managing the file data within the internal program
buffer. Later chapters will add features for inserting and deleting data
in the file buffer.
The chapter has also presented a basic routine for displaying multi-
ple evenly spaced lines within the window. Subsequent chapters will
add features that allow the program to scroll the contents of the win-
dow and to force the updating of specific window areas.

# Figure 3.31
# This MAKE file prepares the program of Figures 3.32 and 3.33.
#
FIG3 33.OBJ : FIG3 33.C
cl /W2 /c /7;p /C;%Ns FT!f :3_33.C

FIG3 33®EXE : FIG3


link /NOD FIG3
- 33.ORE FIG3 32.DEF
33.OBJ,, NUL, OS2.LIB SLIBCE.LIB, FIG3 32.DEF

• Figure 3.31..
A MARE file for preparing the example program

Figure 3.32
; Linker definition file for the program listed in Figure 3.33®
NAME FIG3 33
I I
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 3.32..
A linker definition file for preparing the exanple progran
• 136 Programmer's Guide to the os/2PresentationManager

/*
Figure 3.33

Version 2 of the Presentation Manager text editor example program.


This version performs the following additional tasks:
o Obtains the name of a text file from the command line.
o Reads the file into dynamically allocated memory.
o Displays as many lines from the beginning of the f ile as will fit
within the client window.
*/

#def ine INCL GPI


#def ine INCL-WIN /: ::::::: ::: ;I:::: :::::::: ::::::::::::: :/
#include <OSZ.H>
#include <STDIO.H> /* C library header files: */
#include <PROCESS.H>
#include <IO.H>
#include <STRING.H>
#include <STDLIB.H>

/*** Window procedure declaration. *******************************************/


MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

/*** Declarations / definitions for file- and buffer-management module. ******/


#def ine LINEBUFSIZ /* Size of buffer for holding lines.
#def ine ERROPEN /* Error: opening file.
#def ine ERRTOOBIG /* Error: file too large.
#def ine ERRMAXLINES /* Error: maximum file lines exceeded.
#def ine ERRALLOC /* Error: heap allocation.

¥::: :=£=:±±e£¥:::) '; int ErrorNumber/; [n;tis:i:::sb:££:=-:::::::e:tr¥:8T]e

;i;R:::::;:i:i::i:::I::::ii::L (; ::::s:::i::::::i:;::;nE:::::i.
int LastLine = -1; /* Number of last line in buffer.
HHEAP HHeap = NULL; /* PM heap handle.

/*** Utility function declarations. ******************************************/

¥::: E:::r:¥:: i::::c:¥:;;age, ; ,: :=:::n:=:o=h:e:=as:6g:::.Program. :,


/*** GlobaL var±abLes. *******************************************************/

HWND HFrame; /* Handle to main frame window


HAB HAncBlk; /* Handle to anchor block.
HMQ HMesQue; /* Message queue handle.

void main (int argc, char *argv[])

• Figure 3.33..
The source code file for the example program
ManagingMemory 137 .

(
int ReadError = 0; /* Error occurred reading file.
int UsageError = 0; /* No file name given on command line.
HWND Hclient; /* Handle to main client window.
QMSG QueMess; /* Message structure.
ULONG CtlData = /* Control windows to include.
FCF MINmx /* Minimize/maximize box.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
/*** Initialize the buffer-management module. ********************************/
Buflnit () ;

/*** Test for file name on command line. *************************************/


if (argc < 2)
UsageError = 1;
else
/*** Read file into editor buffer. *******************************************/
ReadError = ReadFile (argv [1]) ;

/*** Presentation Manager initializations. ***********************************/


HAncBlk = Winlnitialize (0) ; /* Initialize PM system for process. */
HMesQue = WincreateMsgQueue (HAncBlk,O) ; /* Create a message queue. */
WinRegisterclass /* Register procedure for main window.
(HAncBlk, /* Anchor block handle.
„mlN„ , /* Window class name.
Wndproc, /* Window procedure associatedi w/ class.
OL' /* Class style.
0); /* Extra storage bytes.
HFrame = Wincreatestdwindow /* Create parent window.
(END DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style.
&CEIData, /* Address of control data.
O'MAIN„ ,
/* Client window class name.
": PM Text Editor", /* Text for title bar.
OL' /* Client window style.
0, /* Resource module handle.
0, /* Resource identification.
&Hclient) ; /* Address to receive client window hand.
/*** Test for file error conditions. ****************************************/
if (UsageError)
ErrorQuit ("Must specify file name.") ;

• Figure 3.33:
The source code file for the erample program (continued)
• 138 Programmer's Guide to the os/2 Presentation Manager

if (ReadError)
ErrorQuit (ErrorMessage (ReadError) ) ;

/*** Main message-handling loop. *********************************************/


while (WinGetMsg /* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure
0' /* Window filter.
0, /* First message identifier.
0)) /* Last message identifier.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages. */

/*** Relinquish Presentation Manager resources and terminate application. ****/


Quit (0);

} /* end main */

/*** Window procedure and subroutines. ***************************************/


MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

static SHORT ycharTot; /* Total height of characters.


static SHORT ycharDesc; /* Height of character descenders.
static SHORT ywin; /* Vertical size of window in window coord.
static FATTRS FontAttributes ; /* Stores font attributes from GpiQueryFonts
#def ine ID COURIER 99L /* Local font ID.

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle.
USHORT msg, /* The message.
MPAFun mpl , /* Message-specific information.
MPARAM mp2 ) /* Message-specific information.
(
switch (msg)
(
case WM CREATE: /* Message sent when window is first created. */
return Create (hwnd, msg, mpl, mp2) ;
case WM PAINT: /* Message sent when window data is invalid. */
return Paint (hwnd, msg, mpl, mp2) ;

case WM SIZE: /* Message sent whenever window changes size. */


return Size (hwnd, msg, mpl, mp2) ;

default: /* Perform default processing on all other messages. */


return WinDefwindowproc (hwnd,msg,mpl,mp2) ;

• Figure 3.33..
The source code file for the example program (continued)
ManagingMemory 139 .

} /* end switch */
} /* end Wndproc */

/*** Subroutines called by window procedure. *********************************/

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace; /* Presentation space handle.
FONTMETRICS Metrics; /* Structure to hold font dimensions.
LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts

/*** Load Courier monospace font. ********************************************/


GpiLoadFonts
I(::3§3\{bLL\\couR|ER.FONw) ; /: i:::a;a::a::in:a::i:;nt file. :/
/*** Obtain a handle to a presentation space. ********************************/
Hpresspace = WinGetps (hwnd) ;

/*** Obtain information on Courier font. *************************************/


GpiQueryFonts
(Hpresspace, /* Handle to presentation space.
QF_PRIVATE, /* Enumerate only private fonts.
"Courier", /* Font face name.
&Numberstructs, /* Number of FONTMETRICS structuresi returned
(long)sizeof (FONTMETRICS) ,/* Length of structure for EACH font.
&Metrics) ; /* Address of FONTMETRICS structure;(s).

/*** Store font information in global variables. *****************************/

ycharTot = (SHORT)Metrics. IMaxBaselineExt;


ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (FontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes.IMatch = Metrics.IMatch;
strcpy (FontAttributes. szFacename,Metrics. szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes. IAvecharwidth = Metrics. IAvecharwidth ;
FontAttributes.fsType = FATTR TYPE FIXED;
FontAttributes. fsFontuse = 0;
/*** Release presentation space. *********************************************/
WinReleaseps (Hpresspace) ;
return FALSE;

} /* end Create */

• Figure 3.33..
The source code file for the example program (continued)
• 140 Programmer's Guide to the os/2 Presentation Manager

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window coordinates, in pixels.
SHORT StopLine; /* Last line to paint.
POINTL Start; /* Starting position to print string
SHORT LineLength; /* Length of each line displayed.
Hpresspace WinBeginpaint
(hwnd /* Window handle.
0, /* Handle of PS to have clipping region set. */
0); /* Address of variable to set to update region.*/
/*** Create a logical font for this presentation space. **********************/
GpicreateLogFont
( Hpresspace , /* Presentation space handle.
( PSTR8 ) NULL , /* Logical font name: none.
ID COURIER, /* Local font ID.
&F6ntAttributes) /* Struct. specifying font from GpiQueryFonts.
/*** Make the logical font the current character set. ************************/
Gpisetcharset
( Hpresspace , /* Presentation space handle.
ID COURIER) ; /* Local font ID.
WinQuerywindowRect /* Get dimensions of window.
( hwnd , /* Window handle.
&Rect) ; /* Structure to receive coordinates.
WinF i l lRect /* Erase window.
(Hpresspace , /* Presentation space handle.
&Rect, /* Structure containing window coordinates.
CLR WHITE) ; /* Color to use (white) .
/*** Set foreground color used by 'GpicharstringAt'. *************************/
Gpisetcolor
(Hpresspace, /* Presentation space handle. */
CljR BIACK); /* Color to use: black. */

/*** Calculate last line to fit in client window. ****************************/


StopLine = min (LastLine, ywin / ycharTot) ;

/*** Print lines from beginning of file within client window. ****************/
Start.x -0;
for (Line = 0, Start.y = ywin -ycharTot + ycharDesc; Line <= StopLine;
++I,ine, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue;
GpicharstringAt /* Prints string at given position.
(Hpresspace, /* Presentation space handle.

• Figure 3.33..
The source code file for the example program (continued)
ManagingMemory 141 .

&Start, /* Structure containing starting position.*/


(LONG)LineLength, /* Number of characters to print. */
GetLineAddr (Line)) ;/* Address of line
)

WinEndpaint (Hpresspace) ;

return FALSE;

) /* end Paint */

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** Obtain vertical dimension of client window. ****************************/
ywin = SHORT2FROMMP (mp2) ;

return FALSE;

} /* end Size */

/*** Buffer- and file-management module **************************************/

#define MAXLINES 4096 /* Maximum number of lines in buffer. */


static struct /* Stores information on each line. */
(
PCH LineAddress; /* Far address of block containing line. */
unsigned char LineLength; /* Length of line (includes \n and \0). */
)
LineTable [MAXLINES] ;

static char LineBuffer [LINEBUFSIZ] ; /* Temporary line buffer.


static unsigned Lineselector; /* Selector for 'LineBuffer'.
::::i: :E:iE::Ss:i::::f;et, /: g:f:::ofo:f'::::B::a:it.
void Buflnit (void) /* Initializes the buffer-management module.
(
PCH Farptr;

/*** Obtain selector and offset of temporary line buffer. ********************/


Farptr = (char far *)LineBuffer;
Lineselector = SELECTOROF (Farptr) ;
Lineoffset = OFFSETOF (Farptr) ;

} /* end Buflnit */

char *ErrorMessage /* Returns a string that describes an error code. */


(int ErrorNumber) /* The error code. */
(
static char *MessageTable [] =

• Figure 3.33®®
The source code file for the example program (continued)
• 142 Programmer's Guide to the os/2 Presentation Manager

(
''no error",
''file open failure",
''file too large",
''maximum lines exceeded",
"heap memory allocation failed",
''unidentified error''
in
if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))
ErrorNumber = sizeof (MessageTable) / sizeof (char *) - 1;
return MessageTable [ErrorNumber] ;

} /* end ErrorMessage */

int ReadFile /* Reads file into editor.


(char *FileName) /* Name of file.
(
FILE *PtrFile; /* File stream pointer.
long FileLength; /* Size of file.
USHORT Heapsize; /* Size of allocated heap.
NPCH Heapoffset; /* Offset of blocks within heap.
unsigned char LineLength /* Length of lines.
PCH Farptr: /* Temporary far pointer.
/*** Open the £±Le. **********************************************************/

if ((PtrFile = fopen (FileName,"r")) == NULL)


return (ERROPEN) ;

/*** Obtain and test file length. ********************************************/


if ((FileLength = filelength (fileno (PtrFile))) == -1)
return (ERROPEN) ;

if (FileLength > 50000)


return (ERRTOOBIG) ;

/*** Allocate a heap to hold file lines. *************************************/

/* Make heap 20% larger than size of file.


Heapsize = (USHORT) (FileLength + FileLength / 5) ;
HHeap = WincreateHeap
(0' /* Segment address: 0 means allocate new segment.
Heapsize /* Initial heap size.
/* Minimum increase size: 0 means use default.
/* Minimum # of dedicated free lists: none.
/* Maximum # of dedicated free lists: none.
/* Options: none.
/*** Obtain selector to heap segment. ****************************************/

• Figure 3.33..
The source code file for the exJrmple program (continued)
ManagingMemory 143 .

Farptr = WinLockHeap (HHeap) ;


Heapselector = SELECTOROF (Farptr) ;

/*** Read each line in file into a separate block allocated from heap. *******/
LastLine = -1;
while (fgets (LineBuffer,LINEBUFSIZ-1,PtrFile) != NULL)
(
/*** Test for line limit --update 'LastLine'. *********************/
if (++LastLine >= MAXLINES)
return (ERRMAXLINES) ;

/*** Calculate length of line. *************************************/


LineLength = (unsigned char)strlen (LineBuffer) + 1;/* Include null*/

/*** Insert '\n' into overlength lines. ****************************/


if (LineLength == .LINEBUFSIZ - 1 &&
LineBuffer [LINEBUFSIZ -3] != '\n')
(
LineBuffer [LINEBUFSIZ -2] = '\n';
LineBuffer [LINEBUFSIZ -1] = '\0';
++LineLength ;
)

/*** Allocate a block from heap to hold the line. ******************/


Heapof fset = WinAllocMem
(HHeap, /* Heap handle. */
LineLength) ; /* Length of line to store. */
if (Heapof fset == NULL)
return (ERRALLOC) ;

/*** Copy line into heap block. ************************************/


movedata (Lineselector, Lineoffset,Heapselector,
(unsigned) Heapof fset , LineLength) ;
/*** Insert line information into the table. **********,*************/
LineTable [LastLine] .LineAddress = MAKEP (Heapselector,Heapoffset) ;
LineTable [LastLine] .LineLength = LineLength;
)

/*** CLose the file. *********************************************************/


fclose (PtrFile) ;
return (0) ;

} /* end of ReadFile */

SHORT GetLineLength (int Line) /* Gets length of line in buffer. */


(
if (Line < 0 I I Line > LastLine)
return 0;
else
/* Extract line length from table, excluding '\n' and '\0'.
return LineTable [Line].LineLength -2;

• Figure 3®33..
The source code file for the example program (continued)
• 144 Programmer's Guide to the os/2PresentationManager

} /* end GetLineLength */

PCH GetLineAddr (int Line) /* Gets address of buffer line. */


(
if (Line < 0 I I Line > LastLine)
return NULL;
else
return LineTable [Line].LineAddress;

} /* end GetLineAddr */

/*** Utility functions. ******************************************************/

void ErrorQuit /* Terminate program due to fatal error condition. */


(char *Message) /* Error message to display to user. */
(
char Buffer [60];
sprintf (Buffer,"Program Error: %s",Message) ;
WinMessageBox /* Display a message box.
(HWND DESKTOP, /* Handle of parent: desktop window.
HFrame , /* Handle of owner: frame window.
Buffer, /* Message text.
''PM Text Editor",
/* Caption.
0' /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB ICONHAND) ; /* Display a hand icon.
Quit (1); /* Call normal termination function.
} /* end ErrorQuit */

void Quit
(int Errorcode) /* Process termination status.
/*
Calls Presentation Manager termination functions and ends program
with specified error code.
*/
(
if (HHeap != NULL)
WinDestroyHeap (HHeap) ;
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue) ;
WinTerminate (HAncBlk) ;
exit (Errorcode) ;

) /* end Quit */

• Figure 3.33..
The source code file for the example program (continued)
147.

.I
he version of the example program presented in this
chapter allows you to view any portion of the file that is
specified on the command line. Horizbntal and vertical
scroll bars are added to the standard Window, allowing
you to scroll through the file in any direction using either the mouse or
thekeyboard.Althoughthisversiondoesnotyetperinityoutomodify
or add file data, it serves as a convenient utility for viewing a text file
within a Presentation Manager window, and you might want to keep a
copy of the program for this purpose.
In this chapter you will learn how to create horizontal and vertical
i

scroll bars and how to maintain the scroll bar sliders in their correct
relativepositions;youwillleamhowtoscrouthecontentsofthescreen
in response to messages from the scroll bars; and you will learn how to
invoke the window-drawing routine whenever needed. You will also
discover how to increase efficiency by redrawing only the portion of the
window that requires updating (the invalid region). Finally, the chapter
offers several suggestions for enhancing the program.
Note that the buffer-management module is unaltered from the pre+
vious version; the current version, however, is able to display any por-
tion of the data within the buffer and not just the first page. The complete
program listing is given in Figure 4.25, at the end of the chapter.

• CREATING THE SCROLLBARS


You can add horizontal and vertical scroll bars to the collection of
windows created by Wincreatestdwindow by including the
FCF_HORZSCROLL and FCF_VERTSCROLL styles in the value as-
signed to the control window variable (CtlData in the example pror
gram; the address of this variable is passed as the third parameter).
Wincreatestdwindow is described in Figure 2.5, ahd the styles you
can select are listed in Tables 2.2, 2.3, and 2.4.) Figure; 4.1 illustrates the
standard window created by the version of the example program
presented in this chapter, and shows the appearance and position of the
two scroll bars.
Figure 4.2 illustrates the components of horizontal and vertical scroll
bars, and the actions these components initiate. (The figure also gives
the codes, such as SB_LINEUP, that the system uses tb indicate specific
• 148 Programmer's Guide to the os/2 Presentation Manager

actions; these codes are explained later in the chapter.) By clicking the
mouse pointer on various parts of the horizontal scroll bar, you can
scroll the window right or left either by a single column or by a ``page"
(in this program, a page is six columns). You can also move the screen to
any horizontal position in the file by clicking and dragging the slider
(that is, clicking the mouse with the pointer on the slider and moving
the pointer with the button held down). Scrolling horizontally enables
you to view various portions of lines that are longer than the current
width of the window. The position of the slider indicates the relative
horizontal position of the window with respect to the file.
You can use the vertical scroll bar in a similar fashion to scroll up and
down by one line or one page (a page is an entire screen of data), and to
move up or down to any relative position in the file. As you will see, the
program also allows you to scroll through the file using the arrow keys
and the Pgup and PgDn keys.
Note that in this book, the term scrozJ€7ig #p means that the view
within the window moves toward the beginning of the file (even
though the lines actually move down), and scroJJz.77g dozo77 means that
the view moves toward the end of the file. Also, scrozzj7zg r3.gJtf means
moving the view in the window toward the right ends of the lines, and
scroJJj77g Jc# means moving the view toward the beginnings of the lines.

• Figure 4.1..
The standard window created by the current version of the exanple program
UsingscrollBars 149 .

Scroll Up One Line


(SB_LINEUP)
E H B nlE I
Scroll Up One Page
(SB_PAGEUP)

SLIDER
Drag to Move to Plelative File Position
(SB_SLIDEBPOSITION)

Scroll Down One Page


(SB_PAGEDOWN)

Scroll Down One Line


(SB_LINEDOWN)

Scroll Left One "Page" Scroll Right One "Page"


(SB_PAGELEFT) (SB_PAGEPIIGHT)

Scroll Left SLIDEPI Scroll Right


One Column Drag to Move to One Column
(SB_LINELEFT) Plelative Position (SB_LINEF3IGHT)
(SB_SLIDEBPOSITION)

€ +
• Figure 4.2..
The anatony of the horizontal and vertical scroll bars
•150 Programmer's Guide to the OS/2 Presentation Manager

After the function main calls Wincreatestdwindow, but before it


enters the message processing loop, it calls WinsetFocus (Figure 4.3) to
assign the current /oct/s to the client window, as follows:

WinsetFocus (HWND DESKTOP, Hclient) ,.

The window with the focus is the one that receives keyboard input
through messages (note that at a given time, there may be no focus win-
dows). The focus must be assigned to the client window so that the
client window procedure will receive any messages generated by the

WinsetFocus
Purpose..
Assigns the focus to the specified window.

Prototype..
BO0L APIENTRY WinsetFocus
(HWND hiirndDesktop, Handle of the desktop window,
HWND DESKTOP.
HWND hwndsetFocus) ,. Handle of the window to receive the
focus (which must be a descendant
window of the desktop window).

Return Value ..
TRUE if the function was successful; FALSE otherwise.

Notes..
You can determine the window that has the current focus by
calling WinQueryFocus.

RelatedFunctions..
WinQueryFocus (Figure 5.10)

• Figure 4.3..
The WinsetFocus Presentation Manager function
UsingscrollBars 151 .

arrow or Pgup/PgDn keys. Note that the window with the focus ap-
pears on top of all other windows.
There are two more common terms related to the concept of the focus
window. First, the ¢c£1.zJc zt7!.#dozu is the top-level window (that is, an im-
mediate child of the desktop window) that is placed above all other top-
level windows. If the active window is a standard window, its title bar
and sizing border appear highlighted; if it is a dialog box (see Chapter
8), its entire border is highlighted to indicate the active status. The focus
window (if one currently exists) is always either the active window or a
descendant of the active window. The active and focus windows are set
either by a program action (such as calling WinsetFocus), or by a user
action (through the keyboard or mouse). Second, th.e program that cur-
rently owns the active window is known as the ¢cfi.z7c ¢ppJ1.co£!.o71.
Other than specifying the two scroll bar styles in the call to Win-
Createstdwindow, and calling WinsetFocus to assign the focus to the
client window, the function main is the same as it was in the previous
version of the example program. To initialize and maintain scrou bars,
however, the window procedure of the current version must provide
some additional code in the routines that process the WM_CREATE
and WM_SIZE messages (these messages were described in Chapter 3).

The WM_CREATE Message


As mentioned in Chapter 3, the WM_CREATE message (Figure
3.16) is sent to the client window immediately after the window has
been created, but before it becomes visible. The new version of the Cre-
ate function, which processes this message, is listed in Figure 4.4. In ad-
dition to the tasks performed by the previous version, Create obtains
the character zu!.dffe for the Courier font from the lAvecharwidth field
of the FONTMETRICS structure (see Figure 3.21). This value is stored in
the variable xchar and win be used by the routines that process the
WM_SIZE and WM_PAINT messages, described later in the chapter.
Note that although this field is labeled as the ¢z7cr¢ge character width,
the characters belonging to the Courier font are uniformly spaced, and
therefore the field actually supplies the exact, constant character width.
The Create function also obtains the handles for the horizontal and
vertical scroll bars, which are required by several of the routines that
®152 Programmer's Guide to the OS/2 Presentation Manager

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPAFun mpl, MPARAM mp2)
(

::£T#:==::§a::trics; /: 5::::::::i:: ::::ef:::d::iensions.


LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts.
GpiLoadFonts /* Load Courier font.
(HAncBlk, /* Anchor block handle.
"\\OS2\\DLL\\COURIER.FON"); /* Full path name of font file.

Hpresspace = WinGetps (hwnd) ;

GpiQueryFonts /* Obtain information on Courier font.


(Hpresspace, /* Handle to presentation space.
9:6:::¥£:=, ,: E:::e=::: :::::te fonts.
&Numberstructs, /* Number of FONTMETRICS structures returned
(long)sizeof (FONTMETRICS) ,/* Length of structure for EACH font.
&Metrics) ; /* Address of FONTMETRICS structure(s).

xchar = (SHORT) Metrics. IAvecharwidth;


ycharTot = (SHORT) Metrics. IMaxBaselineExt;
ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (FontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes.IMatch = Metrics.IMatch;
strcpy (FontAttributes. szFacename,Metrics. szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes. IAvecharwidth = Metrics. IAvecharwidth;
FontAttributes. fsType = FATTR TYPE FIXED;
FontAttributes. fsFontuse = 0;
WinReleaseps (Hpresspace) ;

/*** Get handles to horizontal and vertical scroll bar windows. **************/
HHScroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT,FALSE) , /* Handle to parent */
/* window (frame). */
FID HORZSCROLL) ; /* Identifier for vertical scroll bar. */
HVscroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT,FALSE) , /* Handle to parent */
/* window (frame). */
FID VERTSCROLL) ; /* Identifier for vertical scroll bar. */
return FALSE;

} /* end Create */

• Figure 4.4..
The function Create from the example program
UsingscrollBars 153 .

process subsequent messages. Create first obtains the horizontal win-


dow handle by calling the Presentation Manager function Winwin-
dowFromlD (Figure 4.5), which returns the handle of a child window.
The program passes the handle of the frame window (which is the
parent of both scroll bar windows) and the 3.dc77fz.¢.cr of the horizontal
scroll bar (FID HORZSCROLL); WinwindowFromlD returns the fe¢7id-
Zc of the horizontal scroll bar.
To obtain the handle of the frame window, Create must call another
Presentation Manager function, WinQuerywindow (Figure 4.6), which
returns the handle of the window having the selected relationship to a
specified window. Create passes the values hwnd and QW_PARENT to
request the handle of the parent of the current window; the parent of
the current window is the frame window. Create must call WinQuery-
Window rather than simply passing the global variable HFrame, be-
cause at this point in the program, Wincreatestdwindow has not yet
returned and therefore HFrame does not contain a valid handle.

WinwindowFromlD
Purpose..
Returns the handle belonging to a child window.

Prototype..
IIWND APIENTRY WinwindowFromlD
(IIWND hwndparent , Handle of the parent of the window.
USHORT id) ,. Identifier of the child window.

Return Value ..
If successful, returns the handle of the window that is the
child of the window specified by the first parameter, and
that has the ID given by the second parameter. If an error oc-
curs, the value NULL is returned.

• Figure 4.5..
The WENindowFrornlD Presentation Manager function
• 154 Programmer's Guide to the os/2 Presentation Manager

WinQuerywindow
Purpose..
Returns the handle of the window that has the selected
relationship to a specified window.

Prototype..
IIWND APIENTRY WinQuerywindow
(HWND hwnd, Handle of the window to query.
SHORT cnd, Specifies the relationship of the window
whose handle is to be returned to the
window specified by hwnd; you can select
one of the following values:

Value Meaning
QW_NEXT Next window below
QW_PREV Next window above
QW_TOP Top-most child
window
QW_BOTTOM Bottom-most child
window
QW_NEXTTOP Next top-level
window that would
be activated by the
Alt-Esc key of the
user interface
QW_PREVTOP Previous top-level
window in the
sequence of windows
activated by the
Alt-Esc key
QW_OWNER Owner of the window
QW_PARENT Parent of the window

• Figure 4.6..
The WinQnery:Window Presentation Manager function
UsingscrollBars 155 .

BOOL fLock) ,. If this parameter is TRUE, the window


will be locked; if it is FALSE, the
window will not be locked.

Return Value ..
The handle of the window related to hwnd, or NULL if an
error occurred.

• Figure 4.6..
The WLriQnery:Window Presentation Manager function (continued)

Note that a window I.dc7ifz./z.cr is distinct from a window ha7idJc. A win-


dow handle is a number returned by ffee sysfc777 when it creates a
window; the value of the handle can differ each time a specific win-
dow, such as a scroll bar, is created. A window identifier, however, can
be specified when you create the window (for example, through the
Wincreatewindow function or through a dialog template, discussed in
Chapter 8). When the system creates control windows through the Win-
Createstdwindow function, it assigns each of these windows a
predefined standard identifier. For example, the horizontal scroll bar is
given the identifier FID_HORZSCROLL and the vertical scroll bar is as-
signed FID_VERTSCROLL. Unlike window handles, the identifier for a
specific control window created through Wincreatestdwindow is al-
ways the same. The identifiers for the control windows are listed in
Table 4.1.
In a similar manner, Create next obtains the handle for the vertical
scroll bar. The horizontal scroll bar handle is saved in the variable
HHScroll, and the vertical scroll bar handle is saved in HVscroll.

The WM_SIZE Message


WM_SIZE is the next message processed by the client window
procedure during window creation, and subsequently each time the
window changes size. The new version of the routine that processes this
message, Size, is listed in Figure 4.7. This routine first obtains the cur-
rent vertical dimension (ywin) ¢71d horizontal dimension (xwin) of the
• 156 Programmer's Guide to the os/2 Presentation Manager

• Table 4.1.. Identifiers fol|fae Stapdard Control Windows

Identifier Control Window


FID HORZSCROLL Horizontal scroll bar
FID MENI Application menu
FID MINh4jex Minimize / maximize box
FID SIZEBORDER Sizing border
FID SYSMENU System menu
FID TITLEBAR Title bar
FID VERTSCROLL Vertical scroll bar

client window; both of these values will be used by this function and by
the routines that process subsequent messages, such as WM_PAINT.
Next, the function Size calculates the value of TopLineMax, which
contains the largest line number that will be placed at the top of the
window as the window data are scrolled. The expression used to calcu-
late this value,

TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ,.

assures that the window is not scrolled down farther than necessary to
show the last line in the file (remember that file lines are numbered
beginning with 0). Note that as the window becomes smaller vertically,
TopLineMax becomes larger (except in the case where the file data does
not completely fill the window; in this case TopLineMax remains 0).
Therefore, TopLineMax must be recalculated each time the window
changes size; accordingly, the expression is placed in the function Size
rather than in Create.
Once TopLineMax has been calculated, the program reassigns the
variable TopLine, which is the number of the file line currently dis-
played at the top of the window, to make sure that it does not exceed the
maximum value contained in TopLineMax. (TopLine is initialized to 0.)
Note that the WM_PAINT message is sent shortly after the WM_SIZE
1.
UsingscrollBars 157 .

message; the routine that processes WM_PAINT will use the updated
value of TopLine to paint the appropriate lines within the window.
At this point, the function Size sets the range and position of the
slider within the vertical scroll bar (see Figure 4.2). Note that your pro-
gram is responsible for maintaining the slider; the scroll bar does 7io£
perform this action automatically (as you will see, the only automatic

lmESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

/*** Obtain vertical and horizontal dimensions of client window. ************/


ywin = SHORT2FROMMP (mp2) ;
xwin = SHORTIFROMMP (mp2) ;

/*** Update 'TopLine' and adjust vertical scroll bar position. **************/
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
TopLine = min (TopLine,TopLineMax) ;

W±nse;gs:=:±:±oLLBAR, ;; i::¥§::I::I;:!±=:::::±i::: :::::±°:;r

MPFEOM2SHORT (TopLine, 0) , /* Position.


MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

/*** Enable scroll bar only if needed (TopLineMax > 0). ****************/
WinEnablewindow

i:¥::::i:i 7 1 : o,; ,: E:::::e::L§a=:i:;x¥eT:±8:i Scroll bar. :,


/*** Update 'Firstcol' and adjust horizontal scroll bar position. ************/
FirstcolMax = LINEBUFSIZ - 2 - xwin / xchar;
Firstcol = min (Firstcol, FirstcolMax) ;
w±nseTS¥Sgro]] , ,: a:±¥SEe::r±:::::t ::=:±:n::: :::::±o:;r:,
SBM SETSCROLLBAR, /* Set position & range. */
MPFEOM2SHORT (Firstcol, 0) , /* Position. */
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range. */

return FALSE;

} /* end Size */

• Figure 4.7:
The function Size from the example progran
• 158 Programmer's Guide to the os/2 Presentation Manager

action taken by a scroll bar is to send messages to report input from the
user). You must set the following two values for the slider:

• The slider rfl7igc, which is specified as a minimum value (the


value represented when the slider is at the top of the scroll bar)
and a maximum value (the value represented when the slider is
at the bottom of the scroll bar). In the example program, the posi-
t±or\ of the sLider ±s used to ir\dicaLte the number of the line that ap-
pears at the top of the window. Therefore, this prograLrr\ always sets
the minimum range value to 0, and the maximum range value to
TopLineMax.
The current slider poszt!.o71 within the specified range. In the ex-
ample program, this is simply TopLine.

Once TopLineMax and TopLine have been calculated, the program


must set the slider position and range based upon the new values of
these variables. The two slider parameters are set by sending a message
directly to the vertical scroll bar window.
In addition to receiving messages, a window procedure c¢71 sc7id 777cs-
s¢ges fo o#zcr zu€.77dozus (as you will see later, it can even send messages to
itself). Sending messages to window procedures provided by the
Presentation Manager is an important general method for obtaining ser-
vices from the system. The collection of predefined messages you can
send to system window procedures is thus a significant extension of the
basic Presentation Manager API.
When you send a message to a scroll bar window, the system invokes
the window procedure associated with this window (which by default
is a procedure provided by the system), passing it the parameters you
have supplied. The example program sends the message by calling the
Presentation Manager function WinsendMsg (Figure 4.8). The first
parameter to this function is the handle of the target window
(HVscroll, the vertical scroll bar window). The second parameter is the
identifier of the actual message, SBM_SETSCROLLBAR (Figure 4.9),
which causes the vertical scroll bar procedure to set both the range and
the position of the scroll bar. The next two parameters specify the mes-
sage parameters to be passed to the target window procedure
(equivalent to the mpl and mp2 parameters processed by the client
window procedure). The first message parameter gives the current
UsingscrollBars 159 .

slider position (the low-order word is set to the position and the high-
order word is 0), and the second gives the slider range (the low-order
word contains the minimum range value and the high-order word the
maximum value). These parameters are constructed using the OS/2
macro MPFROM2SHORT, described in Table 3.2.
Note that WinsendMsg causes the system to send a message by
directly calling the window procedure belonging to the target window;
the message is rzof placed in the message queue. In contrast, the Presen-
tation Manager function WinpostMsg sends a message by placing it in
the message queue of the target window.
The function Size next makes sure that the vertical scroll bar window
is enabled only if the file contains sufficient data to warrant vertical
scrolling. If the scroll bar window is disabled, it still appears on the
screen; however, if the user clicks the mouse on this window, the win-
dow procedure merely beeps and does 71of send messages to the client
window. The program sets the enabled status of this window by calling
the Presentation Manager function WinEnablewindow (Figure 4.10).
The first parameter to this function is the handle of the specific window;
if the second parameter is TRUE, the window is enabled, and if it is
FALSE, the window is disabled. The program passes the handle of the
vertical scroll bar window, and enables this window only if TopLine-
Max is greater than 0 (otherwise, no scrolling is possible).
The program next calculates the value of the program variable First-
ColMax based upon the current window dimensions. This variable
contains the number of the greatest file column that can be displayed at
the far left of the window (the file column number is the offset of a char-
acter within a line in the file buffer). The expression used to calculate
this value,

FirstcolMax = LINEBUFSIZ - 2 - xwin / xchar,.

assures that the window does not scroll farther to the right than is neces-
sary to display the longest possible line in the file (LINEBUFSIZ -2). The
program then updates the value of Firstcol, which contains the num-
ber of the file column currently displayed at the far left of the window,
to make sure that this variable does not exceed the maximum value
contained in FirstcolMax.
Finally, the program sends a message to set the range and position of
the horizontal scroll bar slider in the same manner that it set the vertical
• 160 Programmer's Guide to the os/2 PresentationManager

WinsendMsg
Purpose,
Sends a message to the specified window.

Prototype..
MRESULT APIENTRY WinsendMsg
(HWND hwnd, Handle of the target window.
USHORT msg, The identifier of the message that is being
sent.
MPARAM mpl , The first message parameter; the meaning is
specific to the message.
MPARAM mp2 ) ,. The second message parameter; the meaning
is specific to the message.

Return Value ..
The value that is returned by the window procedure of the
target window.

Notes..
This function causes the system to directly invoke the win-
dow procedure belonging to the target window; the message
is not placed in the window's message queue (you can place
a message in the target window's queue by calling Winpost-
Msg). WinsendMsg does not return until the message has
been processed (unlike WinpostMsg, which returns imme-
diately after the message is placed in the queue).

Relate d Functions ..
WinpostMsg (Figure 12.11)

• Figure 4.8..
The Winser\d:Mss Presentation Manager function
UsingscrollBars 161 .

SBM SETSCROLLBAR
Purpose..
This message is sent to a horizontal or vertical scroll bar win-
dow to cause it to set the range and position of the scroll bar
slider.

Parameters..
ueARAM mpl
low-order word: Slider position.
high-order word: 0
REARAM mp2
low-order word: Low value of range.
high-order word: High value of range.

Return Value ..
TRUE if the operation was successful, or FALSE if an error
occurred.

Notes..
The system procedure for the scroll bar window immedi-
ately redraws the scroll bar to reflect the requested values.
See also SBM_SETPOS (Figure 4.17), which sets only the
slider position.

• Figure 4.9..
The SBM~SETSCROLLBAR Presentation Manager message
• 162 Programmer's Guide to the os/2PresentationManager

scroll bar slider. Note, however, that the WinEnablewindow function is


71of called. Since the maximum visible line length (LINEBUFSIZ - 2)
is much larger than the maximum window width, horizontal scroll-
ing is always permitted. (Note that the scroll bar windows are enabled
by default when they are created.)

WinEnablewindow
Purpose..
Enables or disables the specified window.

Prototype..
BOOL APIENTRY WinEnablewindow
(HWND hwnd, The window handle.
BooL fEnable) ,. If this parameter is TRUE thewindowis
enabled; if it is FALSE, the window is
disabled.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
If the enabled state of the target window is changed through
this function call, this window is sent a WM_ENABLE mes-
sage. The changes in the window's appearance and function
between the enabled and disabled state depend upon the
specific window.

• Figure 4.10..
The WinEnablewindow Presentation Manager message
UsingscrollBars 163 .

PROCESSING
• THE SCROLLBARMESSAGES
As mentioned earlier in the chapter, the only action initiated by
the scroll bar windows is to send messages to the client window to
report input from the user. To generate the actual scrolling of data and
to update the scroll bar slider positions, the client window procedure
must receive and process these messages. The horizontal scroll bar
sends the general message WM_HSCROLL, and the vertical scroll
bar sends the general message WM_VSCROLL. Each of these messages
is accompanied by a code indicating the exact scrolling activity that has
taken place. (Actually, the scroll bar windows send these messages to
their owner, the frame window; the frame window then passes the mes-
sages to the client window.)
Accordingly, the main switch statement of the client window proce-
dure (Wndproc) must contain branches for processing these two new
messages. The current version of Wndproc is listed in Figure 4.11. Note
that this function also contains a branch for the WM_CHAR message,
which will be explained in the next main section, Rerouting Keyboard
Input.

The WM_HSCROLL Message


The horizontal scroll bar sends the WM_HSCROLL message (Fig-
ure 4.12) to the client window (through the frame window) whenever it
receives relevant input from the user. This input can originate either
from the mouse or from the keyboard (the manner in which scroll bars
receive keyboard input is explained in the section on Rerouting Key-
board Input). The WM_HSCROLL message is accompanied by a code
in the high-order word of mp2, which indicates the specific type of
horizontal scroll bar activity. The meanings of these activity codes are
listed in Table 4.2. Note that holding down a keyboard key or mouse
button will cause the appropriate message to be repeated. See also Fig-
ure 4.2, which illustrates the components of the scroll bars associated
with each of the codes used in the example program.
The WM_HSCROLL message is processed by the function HScroll of
the example program, which is listed in Figure 4.13. This function first
• 164 Programmer's Guide to the os/2PresentationManager

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle. */
USHORT msg, /* The message. */
MPARAM mpl , /* Message-specific information. */
MPAFun mp2) /* Message-specific information. */
(
switch (msg)
(
case WM CHAR: /* Message sent when keyboard key is received. */
return Character (hwnd, msg, mpl, mp2) ;
case WM CREATE: /* Message sent when window is first created. */
return Create (hwnd, msg, mpl, mp2) ;
case WM HSCROLL: /* Message sent on horizontal scroll activity. */
return HScroll (hwnd, msg, mpl, mp2) ;

case WM PAINT: /* Message sent when window data is invalid. */


return Paint (hwnd, msg, mpl, mp2) ;
case WM SIZE: /* Message sent whenever window changes size. */
return Size (hwnd, msg, mpl, mp2) ;

case WM VSCROLL: /* Message sent on vertical scroll activity. */


return Vscroll (hwnd, msg, mpl, mp2) ;

default: /* Perform default processing on all other messages. */


return WinDefwindowproc (hwnd,msg,mpl,mp2) ;

} /* end switch */
} /* end Wndproc */

• Figure 411..
The Wndproc function of the example program

determines the number of columns that the window should be scrolled


according to the activity code passed with the message, and assigns this
number to the variable Delta. A negative value in Delta indicates scroll-
ing left, and a positive value scrolling right. The program arbitrarily
scrolls by six columns in response to a page Jc/£ (SB_PAGELEFT) or page
r{.gfrf (SB_PAGERIGHT) message.
Note that there are two methods for processing movement of the
slider. First, as the user drags the slider, the scroll bar sends a rapid
series of messages with the SB_SLIDERTRACK activity code (in the
high-order word of mp2) and the current slider position (in the low-
order word of mp2). If the program can process these messages as fast
as they are sent, it can update the screen and the slider position with
each message. As a result, the screen scrolls wJz{7c the user drags the
UsingscrollBars 165 .

WM HSCROLL
Purpose..
Sent by a horizontal scroll bar window to its owner to report
relevant scroll bar events.

Parameters..
REARAM mpl The scroll bar window identifier.
REARAI mp2
low-order word: Contains the position of the slider if
the high-order word equals
SB SLIDERPOSITION or
SB-SLIDERTRACK; otherwise, it is set
to FALSE.
high-order word: A code for the specific event; these
codes are described in Table 4.2.

Return Value ..
FALSE.

• Figure 4.12..
The WM_HSCROLL Presentation Manager message

slider. If the update routine is lengthy or the machine slow, however,


the program may not be able to process the messages as quickly as they
are received, and the scrolling action becomes rough.
Second, when the user releases the mouse button after dragging the
slider to a new position, the. system sends a s{.77gJc SB SLIDER-
POSITION message specifying the final new position. If the-program
ignores the SB_SLIDERTRACK messages, and processes only the
SB_SLIDERPOSITION message, the window data does not scroll as
the slider is moved, but rather jumps to its final position when the
mouse button is released. On a slower machine, the visual effect of this
method is superior to the first method, and it is the approach used by
the example program. Note also that since the SB_SLIDERPOSITION
message provides an ¢Z7soJt/£c slider position, the program subtracts the
current position (Firstcol) from the position supplied with this mes-
sage to obtain the number of columns to scroll the window (Delta).
• 166 Programmer's Guide to the os/2 Presentation Manager

• Tlable 4.2.. Activity Cod_e_±_f pr_ the yvM_HSCROLL

Code Origin Required Action


SB LINELEFT Clicking on left Scroll one colurm
scroll bar arrow left
or hitting + key
on keyboard
SB LINERIGHT Clicking on right Scroll one colurm
scroll bar arrow right
or hitting i key
on keyboard
SB PAGELEFT Clicking on area Scroll one page
left of slider left
SB PAGERIGHT Clicking on area Scroll one page
right of slider right
SB SLIDERPOSITION Dragging the Scroll screen and
slider to a new update the slider
position and to the new posi-
releasing the tion, encoded in
mouse button the low-order
word of mp2
SB SLIDERTRACK Dragging the If this command
slider causes a is used, update
series of these the screen and
messages slider position
with each
message
SB ENDSCROLL Releasing the Can be ignored
mouse button
(and the pointer is
not on the slider)
UsingscrollBars 167 .

MRESULT EXPENTRY HScro|| (HWND hwnd, USHORT msg, MPARAM mpl, MPAEN mp2)
(

SHORT Delta; /* Amount to scroll. */

/*** Determine amount to scroll. *********************************************/

switct (SHORT2FROMMP (mp2)) /* Switch on code from scroll bar. */

case SB LINELEFT:
Delta --1;
break;
case SB LINERIGHT:
Delta -1;
break;
case SB PAGELEFT:
Delta --6;
break;
case SB PAGERIGHT:
Delta -6;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -Firstcol;
break;
default:
Delta -0;
break;
)
Delta = max (-Firstcol, min (Delta,FirstcolMax -Firstcol)) ;

/*** Scroll the window if necessary. *****************************************/

if (Delta)
(
/*** Adjust first column value. ************************************/
Firstcol += Delta;
/*** Scroll the window data. ***************************************/
Winscrollwindow
(hwnd, /* Handle of client window.
-Delta * xchar, /* Horizontal scroll amount.
0, /* Vertical scroll amount.
0' /* Must be o.
0, /* Must be o.
0, /* Must be o.
0, /* Must be o.
SW INVALIDATERGN) ; /* Invalidate "exposed" region.

/*** Force repainting of invalid window region. ********************/


Winupdatewindow
(hwnd) ; /* Handle of client window. */
/*** Update the position of the horizontal scroll bar slider. ******/
WinsendMsg
(HHScroll, /* Handle to horizontal scroll bar.
SBM SETPOS, /* Set position of slider.

#oM2sHORT (Firstc°L J 0)/* se¢:n:u;:=::e:::i:;:T.


return FALSE;

} /* end HScroll */

• Figure 4.13..
The function HScroll of the example progran
• 168 Programmer's Guide to the os/2PresentationManager

Once the program has determined the initial value for Delta, it ad-
justs this value to make sure that when Delta is combined with First-
Col, the result is within the valid range from 0 to FirstcolMax. This
adjustment is accomplished through the following expression:

Delta = max (-Firstcol, min (Delta,FirstcolMax -


Firstco|) ) ,.

Next, provided that Delta is not 0, the program updates the value of
Firstcol, scrolls the window data, forces repainting of the resulting in-
valid region of the window, and adjusts the horizontal scroll bar posi-
tion. The value of Firstcol is adjusted by the number of columns stored
in Delta. As you will discover, the subsequent actions of this routine
will cause the system to invoke the window-painting function Paint
(through the WM_PAINT message); Paint will use the value in Firstcol
to display the correct portions of the file lines (that is, it will display the
lines beginning with the character having the offset given by Firstcol).
The program scrolls the data within the window by calling the
Presentation Manager function Winscrollwindow (Figure 4.14). This
function scrolls the data in the specified window (hwnd, the client win-
dow) horizontally by the amount specified in the second parameter
(dx), which is assigned the following value:

-Delta * xchar

The - sign is required, because a positive Delta means to scroll the zuz.7z-
dozo to the right and therefore move the d¢f¢ to the left; to move the data
left, however, you must pass Winscrollwindow a negative dx value.
Therefore, Delta and dx must have opposite signs. Note from Figure
4.14 that the scrolling distance is specified in cZczJ1.cc I/71z.fs; for the presen-
tation space used by the example program, these units are screen pixels
(conveniently, the same units used for the total window size and for the
character dimensions).
The last parameter to Winscrollwindow (rgfsw), specifies the scroll-
ing options. The example program passes the value SW_IN-
VALIDATERGN, which causes the function to 1.7it7¢Zz.d¢£c the region of
the window that is left behind when the existing data are moved.
Remember from Chapter 2 that an invalid region of a window is an area
that must be repainted, and when a section of a window becomes
UsingscrollBars 169 .

Winscrollwindow
Purpose..
Scrolls the contents of a window a specified horizontal and
vertical distance.

Prototype..
SHORT APIENTRY Winscrollwindow
(- hund, Handle of window to scroll.
SHORT dr[, The amount (in device units) to move
the window data to the right with
respect to the window (a negative
value moves the data left).
SHORT dy' The amount (in device units) to move
the window data up with respect to
the window (a negative value moves
the data down).
PRECTL prclscroll, Points to a RECTL structure (Figure
2.22) containing the dimensions of the
rectangular section of the window to
be scrolled; a value of NULL causes
the entire window to be scrolled.
PRECTL preclclip, Points to a RECTL structure containing
the dimensions of the clip rectangle.
mGIN hrgnupdate , If not NULL, hrgnupdate is assigned
the region uncovered by the scroll.
PRECTL prclupdate, Points to a RECTL structure that will
be assigned the dimensions of the
rectangle invalidated as a result of
scrolling.

• Figure 4.14..
The Winscldrl:Window Presentation Manager f unction
• 170 Programmer's Guide to the os/2 Presentation Manager

USHORT rgf sw) ,. The scroll options; you may specify


one or more of the following values
(combined with the I operator), or
pass 0 for no options:

Option Meaning
SW SCROLLCHILDREN Scroll an child
windows
SW INVALIDATERGN Invalidate the
region(s) of the
screen that
remain after the
data is scrolled

Return Value ..
One of the following codes, indicating the shape of the in-
valid region remaining after scrolling the window.

Return Value Meaning


RGN ERROR An error occurred
RGN NULL NO region (a NULL rectangle)
RGN RECT Simple rectangular invalid region
RGN COMPLEX Complex invalid region

Notes..
If the window data is scrolled both vertically and horizontal-
ly, a complex invalid region can result (not a simple rec-
tangle). The dimensions of the update rectangle returned by
the WinBeginpaint function, however, are for the smallest
simple rectangle that bounds the entire invalid region.

Related Functions ..
WinBeginpaint (Figure 2.20)

• Figure 4.14..
The WLnscachl:Window Presentation Manager f unction ( continued)
UsingscrollBars 171 .

invalid, the system sends a WM_PAINT message to the window proce-


dure. Therefore, a single call to the Winscrollwindow function not
only moves the existing data within the window, but also automatically
causes the Paint function to fill in all characters from the newly ``ex-
posed" columns of the file. Figure 4.15 illustrates the invalid region
created by scrolling the screen horizontally.
Note, however, that the creation of an invalid region normauy causes
the system to post a WM_PAINT message to the client window mes-
sage queue; the client window will receive this message only after it has
processed all other prior messages waiting in its queue. The problem
with this rather leisurely process is that if the user holds down the
mouse button or keyboard key, the window procedure may receive and
process an entire series of WM_HSCROLL or WM_VSCROLL messages
before it receives the corresponding WM_PAINT messages. The result
is that the window scrolls without updating the invalid region until the
user releases the button or key.
To solve this problem, the example program calls the Winupdate-
Window Presentation Manager function (Figure 4.16) immediately
after scrolling the window data. Winupdatewindow causes the system
to call the window procedure associated with the specified window
(hwnd, the client window) d€+ec£Jy, passing it a WM_PAINT message,
rather than inserting this message into the queue. As a result, the in-
valid region of the window is updated immediately (in fact, Win-
Updatewindow does not return until the WM_PAINT message has
been processed). You might try temporarily removing the Winupdate-
Window call from the example program to observe the effect of not up-
dating the window immediately.
Calling functions that invalidate a section of the client window is the
primary method for a program to modify the data that it displays on the
screen. The ability to invalidate a window region allows a program to
use a single routine for updating the window display in response to the
extemal demands of the system or the internal activities of the program
itself.
Note that you can also explicitly invalidate any region of a win-
dow by calling the WinlnvalidateRect Presentation Manager function
(described in Figure 5.8). Accordingly, one method for scrolling the
window horizontally would be to simply adjust the variable Firstcol
and call WinlnvalidateRect to invalidate the c7tfz.rc cJ!.c7tf tt7z.7tdoco. The
• 172 Programmer's Guide to the os/2 Presentation Manager

client Window Before Scrolling

Client Window After Scrolling


One Column Fight
Invalid
Region

I,
his is line one
his is line two
his is line thre
his is line fou
his is line five

• Figure 4.15..
The invalid area created by scrolling a window horizontally
UsingscrollBars 173 .

Winupdatewindow
Purpose..
Causes the system to send a WM_PAIP`IT message to the
specified window by directly calling the window procedure.

Prototype..
BOOL APIENTRY Winupdatewindow
(IIWND hwnd) ,. The handle of the window to be updated.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
The window procedure of the specified window is called
directly with the WM_PAIP`IT message; this message is 71of
placed in the window's message queue. If the target window
belongs to the current thread, this function does not return
until the WM_PAINT message has been processed.

• Figure 4.16..
The WLnupdate:Window Presentation Manager function

function Paint would then automatically repaint the entire window,


starting at the appropriate character offset within the file lines. Thus,
scrolling could be effected without calling Winscrollwindow. The
problem with this simple approach, however, is that it is noticeably
slower than allowing the system to scroll the window data and then
having the Paint function repaint only the invalid region.
Finally, the HScroll function sends the SBM_SETPOS message (Fig-
ure 4.17) to the horizontal scroll bar to update the position of the slider
to reflect the new file location. Unlike the SBM SETSCROLLBAR mes-
sage described earlier in the chapter, the SBM-_SETPOS message up-
dates only the slider position and not the range (it is not necessary to
update the range unless the window changes size).
• 174 Programmer's Guide to the os/2 Presentation Manager

SBM SETPOS
Purpose..
This message is sent to a horizontal or vertical scroll bar win-
dow to cause it to set the position of the scroll bar slider.

Parameters..
REAEN mpl
low-order word: New position of slider.
high-order word: 0.
I@ARAM mp2 0.

Return Value ..
TRUE if the operation was successful, or FALSE if an error
occurred.

Notes..
The system procedure for the scroll bar window immedi-
ately redraws the scroll bar to reflect the requested values.
See also the message SBM_SETSCROLLBAR (Figure 4.9),
which sets both the slider position and the slider range.

• Figure 4.17..
The SBM_SETPOS Presentation Manager message

The WM_VSCROLL Message


The vertical scroll bar reports scrolling activities by sending the
client window the WM_VSCROLL message, which is exactly analogous
to the WM_HSCROLL message, and is described in Figure 4.18. The
specific activity codes included with this message are defined in Table
4.3, and Figure 4.2 illustrates the components of a horizontal scroll bar
that are associated with each of the codes used in the example program.
The WM_VSCROLL message is processed by the Vscroll function of
the example program, which is listed in Figure 4.19. The basic logic
of this function is identical to that of the HScroll function. Vscroll first
uses the activity code to set the value of Delta, which is the number of
UsingscrollBars 175 .

WM VSCROLL
Purpose..
Sent by a vertical scroll bar window to its owner to report
relevant scroll bar events.

Parameters..
IffARAM mpl The scroll bar window identifier.
REAEN mp2
low-order word: Contains the position of the slider if
the high-order word equals
SB SLIDERPOSITION or
SB-SLIDERTRACK; otherwise, it is set
to FALSE.
high-order word: A code for the specific event; these
codes are described in Table 4.3.

Return Value ..
FALSE.

• Figure 4.18..
The WM_VSCROLL Presentation Manager message

rows the window should be scrolled vertically (a positive value indi-


cates scrolling down). Note that a page-up (SB_PAGEUP) or page-
down (SB_PAGEDOWN) activity code sets Delta to the full number of
complete lines contained in the window (negative or positive), which is
calculated using the following expression:

ywin / ycharTot

Delta is subsequently adjusted so that when it is combined with Top-


Line (the number of the line currently displayed at the top of the win-
dow), the result is within the valid range from 0 to TopLineMax. The
following expression adjusts the value of Delta:

Delta = max (-TopLine, min (Delta,TopLineMax -


TOpLine) ) ,.
• 176 Programmer'sGuidetothe os/2Presentation
Manager

• Table 4.3.. Tfee Actipity codes for the WM_VSCROLL Meyxpg_e

Code Origin Required Action


SB LINEUP Clicking on scroll Scroll one row up
bar up-arrow or
hitting 1 key on
keyboard
SB LINEDOVVN Clicking on scroll Scroll one row
bar down-arrow down
or hitting J key
on keyboard
SB PAGEUP Clicking on area Scroll one page up
above slider
SB PAGEDOWN Clicking on area Scroll one page
below slider down
SB SLIDERPOSITION Dragging the Scroll screen and
slider to a new update the slider
position and to the new posi-
releasing the tion, encoded in
mouse button the low- order
word of mp2
SB SLIDERTRACK Dragging the If this command
slider causes a is used, update
series of these the screen and
messages slider position
with each
message
SB ENDSCROLL Releasing the Can be ignored
mouse button
(and the pointer is
not on the slider)
UsingscrollBars 177 .

MRESULT EXPENTRY Vscroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

SHORT Delta; /* Amount to scroll. */

/*** Determine amount to scroll. *********************************************/


switch (SHORT2FROMMP (mp2)) /* Switch on code from scroll bar. */
(
case SB LINEUP:
Delta --1;
break;
case SB LINEDOWN:
Delta -1;
break;
case SB PAGEUP:
Delta = -ywin / ycharTot;
break;
case SB PAGEDOWN:
Delta = ywin / ycharTot;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -TopLine;
break;
default:
Delta -0;
break;
)
Delta = max (-TopLine, min (Delta,TopLineMax -TopLine)) ;

/*** Scroll the window if necessary. *****************************************/

if (Delta)
(
/*** Adjust top line value. ****************************************/
TopLine += Delta;

/*** Scroll the window data. ***************************************/


Winscrollwindow
(hwnd, /* Handle of client window.
0, /* Horizontal scroll amount.
ycharTot * Delta, /* Vertical scroll amount.
0, /* Must be o.
0, /* Must be 0.
0, /* Must be o.

8* INVALIDATERGN) ; /: ¥:::l=:a:; "exposed" region.

/*** Force repainting of invalid window region. ********************/


Winup?:::¥i?d°W /* Handle of client window. */

/*** Update the position of the vertical scroll bar slider. ********/
WinsendMsg
(HVscroll , /* Handle to vertical scroll bar. */
SBM SETPOS /* Set position of slider. */

• Figure 4.19..
The function Vscro+i of the example program
• 178 Programmer's Guide to the os/2 Presentation Manager

} #;?ROM2SHORT (TOPLine,0) J/: §:::::tp::::::::.n/a. :/


return FALSE;

} /* end Vscroll */

• Figure 4.19..
The function Vscrchl of the example program (continued)

Client Window Before Scrolling

this is line two


Client Window After Scrol lingine
this is line three
Down One L
this is line four
this is line five
Invalid F3egion

• Figure 4.20..
The invalid area created by scrolling a window vertically
UsingscrollBars 179 .

If the final value of Delta is not equal to 0, the program proceeds to


update TopLine, to scroll the window data, to force the updating of the
client window, and finally, to set the horizontal slider to the correct
position. These steps are the same as those performed by the HScroll
function, explained in the previous section. Figure 4.20 illustrates the
vertical scrolling process and the resulting invalid region.

• REROUTING KEYBOARD INPUT


All keyboard input (as well as inouse input) is initially received by
the Presentation Manager itself. The Presentation Manager, however,
notifies the window that currently has the focus of each key that is
pressed or released by sending a WM_CHAR message (Figure 6.1) to
this window. The message parameters that accompany this message
identify the specific key and provide other information. (The keyboard
interface is fully described in Chapter 6.)
When a scroll bar window receives a WM_CHAR message for one of
the arrow keys or for the Pgup or PgDn key, it sends an appropriate
scrolling message to the client window. Therefore, the scroll bar initi-
ates scrolling activity in response to both the mouse ¢71d the keyboard.
In the example program, however, there is one problem. As mentioned
in the section on Creating the Scroll Bars, the client window is assigned
the focus through the WinsetFocus function. Therefore, all keyboard
messages are sent to the client window and are not received by the
scroll bar windows.
The solution to this problem is for the client window to reroute cer-
tain keyboard messages to the appropriate-horizontal or vertical-
scroll bar window. WM_CIIAR messages are processed by the function
Character in the example program, which is listed in Figure 4.21. This
function calls WinsendMsg (Figure 4.8) to send all messages for the
1, J, Pgup, or PgDn key to the vertical scroll bar, and all messages for
the + or i key to the horizontal scroll bar. All other keys are simply
ignored (the function returns FALSE, which tells the system that the key
was not processed).
• 180 Programmer's Guide to the os/2 Presentation Manager

MRESULT EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

/*** Send arrow and Pgup/PgDn key messages to appropriate scroll bars. *******/
switch (CHARMSG (&msg) ->vkey)
(
case VK UP: /* Up-arrow key.
case VK-DOWN: /* Down-arrow key.
case VK-PAGEUP: /* Page Up key.
case VK-PAGEDOWN: /* Page Down key.
return WinsendMsg (HVscro'll, in;g, mpl, mf>2) ;

:::: :K-i:::i: /: ::::::::::wk::;.


return WinsendMsg (HHScroll, msg, mpl, mp2) ;
default:
return FALSE;
)

} /* end Character */

• Figure 4.21..
The function ChaLracteT of the example program

Note that the arrow and Pgup/PgDn keys are among the keystrokes
identified by zJz.rftMJ codes (used to label keys that do not have simple
ASCII character codes). The virtual code is contained in one of the mes-
sage parameters, and it is extracted using the special macro for charac-
ter messages, CHARMSG; virtual keys and the CHARMSG macro will
be explained in Chapter 6. Table 4.4 lists the codes for each virtual key,
the identity of the key, the scroll bar that is sent the key message, and
the message that the scroll bar sends to the client window when it
receives the key.

• UPDATING THE WINDOW


The WM_PAINT message is processed by the Paint function of the
example program, which is listed in Figure 4.22. This function has been
modified from the previous version so that it repaints o77Jy ffec !.7tu¢Jz.d
rcg!.o7i of the window. Like the previous version, Paint begins by calling
WinBeginpaint (Figure 2.20) to obtain a handle to a presentation space;
however, instead of passing 0 as the last parameter, it passes the address
of a RECTL structure (Rect; see Figure 2.22). WinBeginpaint assigns
UsingscrollBars 181 .

• T]able 4.4.. The Virtual K s Processed b the Scroll Bars

Key Eara°t]LR:::£ves Message Sent by


Scroll Bar to
the Key Client Window
VKUP t vertical WM VSCROLL,
SB L-INEUP
VK DOWN J vertical WM VSCROLL,
SB LINEDOWN
VK PAGEUP Pgup Vertical WM VSCROLL,
sB p-AGEur
VK PAGEDOIN PgDn Vertical " VSCROLL,
SB PAGEDOIN
VK LEFT + Horizontal WM HSCROLL,
SB LINELEFT
VK RIGHT i Horizontal " HSCROLL,
SB L-INERIGHT

this structure the dimensions of the invalid region of the client window.
Accordingly, the subsequent call to the function WinFillRect (Figure
2.23), which is passed the address of Rect, erases only the invalid area.
(Note that the call to WinQuerywindowRect is no longer needed.)
Theprogramnowcalculatestherangeoffilelinesthatneedtobedis-
played within the invalid area. StartLine is the first line in this range
and StopLine is the last. These values are calculated as follows:

StartLine = TopLine + (ywin - (SHORT)Rect.yTop) /


ycharTot,.

StopLine = min (LastLine, TopLine +


(ywin -(SHORT)Rect.yBottom) / ycharTot) ,.

StartLine is calculated by adding the number of lines above the begin-


ning of the invalid region to TopLine (the number of the line displayed
at the top of the window). StopLine is derived by adding the number of
• 182 Programmer's Guide to the os/2Presentation
Manager

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARjun mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window coordinates, in window coordinates.
SHORT StartLine; /* First file line to paint.
SHORT Stopljine ; /* Last line to paint.
POINTL Start; /* Starting position to print string.
SHORT LineLength; /* Length of each line displayed.
/*** Get presentation space and coordinates of invalid region in window.
Hpresspace = WinBeginpaint
(hwnd,
0' /: ¥::a:: ::ns.:eto have clipping region Set. :/
&Rect) ; /* Address of struct. to set to invalid region.*/
GpicreateLogFont /* Create a logical font for presentation space*/
(Hpresspace,
( PSTR8 ) NuljL ,
ID COURIER,
&F6ntAttributes)
;; :§§:::::;:::D;::::f::i::e:onstant. ;;
/* Struct. specifying font from GpiQueryFonts. */
Gpisetcharset /* Make logical font the current character set.*/
(Hpresspace , /* Presentation space handle. */
ID COURIER) ; /* Local font ID. */

/*** Erase invalid region only. **********************************************/

WinFillRect

:E£:::::;:, ;: :::i::::::i:n;::i::;:::::;w coordinates.


/*** Set color used by 'GpicharstringAt'. ************************************/
Gpisetcolor
!::r:=E:i?, /: :::::n::t:::: sp:::a:?ndle. :/
/*** Calculate first and last lines to go in invalid region. *****************/
StartLine = TopLine + (ywin - (SHORT)Rect.yTop) / ycharTot;
StopLine = min (LastLine, TopLine + (ywin - (SHORT)Rect.yBottom)
/ ycharTot) ;
/*** Print lines within invalid region. **************************************/
Start.y = ywin -ycharTot * (StartLine -TopLine + 1) + ycharDesc;
Start.x = xchar * (-Firstcol) ;
for (Line = StartLine; Line <= StopLine; ++Line, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue ;
GpicharstringAt /* Prints string at given position. */

• Figure 4.22..
The function Palul of the example program
UsingscrollBars 183 .

i:::i;:::;;;:?::::,,,;;i!:i:i:::::::::i::::a:::::I::.posltlon.;j
)

WinEndpaint (Hpresspace) ;
return FALSE;

) /* end paint */

• Figure 4.22..
TirefunctionPalritoftheexampleprogram(continued)

lines above the end of the invalid region to TopLine; using the min
macro, however, assures that StopLine will not be assigned a value
larger than the number of the last line in the file (LastLine).
Next, the program determines the pixel coordinates of the starting
point of the first line to be displayed (at the top of the invalid region).
The y-coordinate of the starting point, Start.y, is calculated as follows:

Start.y = ywin -ycharTot * (StartLine -TopLine + 1)


+ ycharDesc,.

To determine the x-coordinate of the starting point (Start.x), the pro-


gram does not waste time calculating the horizontal pixel coordinate of
the start of the invalid region and the offset of the character in the file
line that needs to be displayed at this point. Rather, it takes advantage
of the fact that the Presentation Manager automatically clips all charac-
ters that fall outside of the invalid region, and the fact that you can safer
ly specify a starting point to the left of the bounds of the current
window (by passing a negative x-coordinate). The following simple ex-
pression does the trick:

Start.x = xchar * (-Firstcol) ,.

Remember that Firstcol is the offset of the character within the file
line that is to appear at the left edge of the window. The call to Gpi-
CharstringAt, however, always specifies the address of the beg{.777i!.7ig
of the line (the address of character 0 within this line). If Firstcol is 0,
then Start.x is assigned 0, and character 0 gets printed at the left of the
• 184 Programmer's Guide tothe os/2Presentation
Manager

window (pixel coordinate 0). If, however, Firstcol is 1, then character 0


is printed one character space fo ffec Jc# of the window. This character, of
course, is invisible; character 1, however, is printed at the left of the win-
dow, and, if this position is within the invalid region, character 1 is
visible. Values of Firstcol larger than 1 work similarly. Although only
characters within the current invalid region are actually painted (the
other regions within the window already contain the appropriate char-
acters), the value assigned to Start.x assures that the characters printed
are correctly aligned horizontally.
The for loop that prints each line works in the same manner as the
loop in the previous version of Paint.

• ENHANCEMENTS
As mentioned at the beginning of the chapter, the current version
of the example program can be used as a practical utility for viewing
text files within a Presentation Manager window. You might want to en-
hance the program for this purpose by adding one or more of the fol-
lowing features (the techniques are described in subsequent chapters):

• The ability to read in a new file without restarting the program.


This feature could be accessed through a menu item (Chapter 7)
and the file name could be entered through a dialog box (Chap-
ter 8). A file-reading routine is presented in Chapter 8.
• A search feature for finding a specific string within the file. This
facility could also be accessed through a menu item and a dialog
box; an algorithm for searching for a string is presented in Chap-
ter 8.

You could display the name of the current file within the title bar
using the WinsetwindowText function. This technique i5 also
presented in Chapter 8.
UsingscrollBars 185 .

• CONCLUSION
Youcanpreparethecurrentversionoftheexampleprogramusing
the MAKE file listed in Figure 4.23. A linker definition file is given in
Figure 4.24, and the complete source listing for the program is provided
in Figure 4.25.
This chapter has described how to use the facilities of the Presenta-
tion Manager programming environment to view any portion of the file
contained in the internal data buffer. Before presenting the methods for
modifying and saving this data, however, Chapter 5 explores the tech-
niques for creating and mo.ving a cursor to any position within the file.

# Figure 4#ThisMAK .23Efile prepares the program of Figures 4.24 and 4.25

#
FIG4 25.OBJ : FIG4 25.C
I
cl /W2 /c /7;p /r:%Ns FT!f 34_2:F>.C

FIG4 25.EXE : -
FIG4 25.OBT FIG4 24.DEF
link /N OD FIGZ 25.OBJ,, NUL, OS2.LIB SLIBCE.LIB, FIG4_24.DEF

• Figure 4.23..
A MAKE file for preparing the example program

; Figure;Linker, 4.24definition file for the program listed in Figure 4.25

NAME FIG4 25
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 4.24..
A linker definition file for preparing the example program
• 186 Programmer'sGuidetothe os/2Presentation
Manager

Figure 4.25

Version 3 of the Presentation Manager text editor example program.


This version adds vertical and horizontal scroll bars that allow the user
to scroll through the file using the mouse or the arrow and Pgup/PgDn keys.
The program provides a handy utility for viewing text files.
*/

#def ine INCL GPI


#def ine
#include
INCL-WIN
<OSZ.H>
/: ::::::: ::: :::::: :::::::: ::::::::::::: :/
#include <STDIO.H> /* C library header files:
#include <PROCESS.H>
#include <IO.H>
#include <STRING.H>
#include <STDLIB.H>

/*** Window procedure declaration. *******************************************/

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

/*** Declarations / definitions for file- and buffer-management module. ******/


#def ine LINEBUFSIZ /* Size of buffer for holding lines.
#def ine ERROPEN /* Error: opening file.
#def ine ERRTOOBIG /* Error: file too large.
#def ine ERRMAXLINES /* Error: maximum file lines exceeded.
#def ine ERRALLOC /* Error: heap allocation.
void Buflnit (void) /* Initializes buffer management module
:::rR:::=:::e;::g= {:::eE:::r¥umber/i Re::sR::::n:n::r::i:::S5:=f:::±ng
SHORT GetLineLength (int Line) ; /* Gets length of line in buffer.
PCH GetLineAddr (int Line) ; /* Gets address of line in buffer.
int LastLine = -1; /* Number of last line in buffer.
HHEAP HHeap = NULL; /* PM heap handle.

/*** Utility function declarations. ******************************************/

¥:i: ===:r?I:: i:::=c:¥:;;age) ; /: :::::n:::a:h:e;:as:6g:::.Program. :/

/*** Global variables. *******************************************************/

HWND HFrame; /* Handle to main frame window.


HAB HAncBlk; /* Handle to anchor block.
HMQ HMesQue; /* Message queue handle.

• Figure 4.25..
The source code file for the example program
UsingscrollBars 187 .

void main (int argc, char *argv[])


(
int ReadError = 0; /* Error occurred reading file.
int UsageError = 0; /* No file name given on command line.
HWND Hclient; /* Handle to main client window.
QMSG QueMess; /* Message structure.
ULONG CtlData = /* Control windows to include.
FCF HORZSCROLL /* Horizontal scroll bar.
FCF-MINmx /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEB0RDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR /* Title bar.
FCF-VERTSCROLL; /* Vertical scroll bar.
Buflnit () ;
if (argo < 2)
UsageError = 1;
else
ReadError = ReadFile (argv [1]) ;
HAncBlk = Winlnitialize (0) ; /* Initialize PM system for process. */
HMesQue = WincreateMsgQueue (HAncBlk,0) ; /* Create a message queue. */

WinRegisterclass /* Register procedure for main window.


(HAncBlk, /* Anchor block handle.
''mlN„ , /* Window class name.
Wndproc , /* Window procedure associated w/ class.
OL' /* Class style.
0); /* Extra storage bytes.
HFrame = Wincreatestdwindow /* Create parent window.
(HWND DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style.
&cEIData , /* Address of control data.
''mlN„ ' /* Client window class name.
'': PM Text Editor", /* Text for title bar.
OL' /* Client window style.
0' /* Resource module handle.
0, /* Resource identification.
&Hclient) ; /* Address to receive client window hand.
if (UsageError)
ErrorQuit ("Must specify file name.") ;
if (ReadError)
ErrorQuit (ErrorMessage (ReadError) ) ;

/*** Give focus to client window. ********************************************/

WinsetFocus
(HWND DESKTOP, /* Handle for desktop window.
Hclierit) ; /* Client window handle.

• Figure 4.25..
The source code file for the example program (continued)
• 188 Programmer's Guide to the os/2 Presentation Manager

while (WinGetMsg /* Get messages until WM QUIT.


(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure
0, /* Window filter.
0, /* First message identifier.
0)) /* Last message identifier.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

Quit (0) ;

} /* end main */

/*** Window procedure and subroutines. ***************************************/


MRESULT Character (HWND hwnd, USHORT msg, MPAEN mpl, MPARAM mp2
MRESULT Create (HWND hwnd, USHORT msg, MPAF" mpl, MPARAM mp2
MRESULT HScroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2
MRESULT Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2
MRESULT Size (HWND hwnd, USHORT msg, MPAF" mpl, MPAF" mp2
MRESULT Vscroll (HWND hwnd, USHORT msg, MPAFun mpl , MPARAM mp2

static xchar ; /* Character width.


static ycharTot; /* Total height of characters.
static ycharDesc ; /* Height of character descenders.
static xwin ; /* Horizontal size of window.
static ywin ; /* Vertical size of window.
static HVscroll ; /* Handle to vertical scroll bar window.
static HHScrol i ; /* Handle to horizontal scroll bar window.
static int Firstcol; /* Character to be in first column position.
static int FirstcolMax; /* Maximum value of 'Firstcol'.
static SHORT TopLine = 0; /* Number of top line in window.
static SHORT TopLineMax; /* Maximum value of 'TopLine'.
static FATTRS FontAttributes /* Stores font attributes from GpiQueryFonts
#def ine ID COURIER 99L /* Local font ID.

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle.
USHORT msg, /* The message.
MPARAM mpl , /* Message-specific information.
MPARAM mp2) /* Message-specific information.
(
switch (msg)
(
case WM CIIAR: /* Message sent when keyboard key is received. */
return Character (hwnd, msg, mpl, mp2) ;
case WM CREATE: /* Message sent when window is first created. */
return Create (hwnd, msg, mpl, mp2) ;
case WM HSCROLL: /* Message sent on horizontal scroll activity. */

• Figure 4.25..
The source code file for the example program (continued)
UsingscrollBars 189 .

return HScroll (hwnd, msg, mpl, mp2) ;


case WM PAINT: /* Message sent when window data is invalid. */
return Paint (hwnd, msg, mpl, mp2) ;
case WM SIZE: /* Message sent whenever window changes size. */
return Size (hwnd, msg, mpl, mp2) ;
case WM VSCROLL: /* Message sent on vertical scroll activity. */
return Vscroll (hwnd, msg, mpl, mp2) ;
default: /* Perform default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;

} /* end switch */
} /* end Wndproc */

/*** Subroutines called by window procedure. *********************************/

MRESULT EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

/*** Send arrow and Pgup/PgDn key messages to appropriate scroll bars. *******/
switch (CIIARMSG (&msg) ->vkey)
(
case VK UP: /* Up-arrow key.
case VK-DOWN: /* Down-arrow key.
case VK-PAGEUP: /* Page Up key.
case VK-PAGEDOWN: /* Page Down key.
return WinsendMsg (HVscroll, msg, mpl, mp2) ;
case VK LEFT: /* Left-arrow key.
case VK-RIGHT: /* Right-arrow key.
return WinsendMsg (HHScroll, msg, mpl, mp2) ;
default:
return FALSE;
)

} /* end Character */

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace; /* Presentation space handle.
FONTMETRICS Metrics; /* Structure to hold font dimensions.
LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts
GpiLoadFonts /* Load Courier font.
(HAncBlk, /* Anchor block handle.
"\\OS2\\DLL\\COURIER.FON") ; /* Full path name of font file.

Hpresspace = WinGetps (hwnd) ;

• Figure 4.25..
The source code file for the erample program (continued)
• 190 Programmer's Guide to the os/2 Presentation Manager

GpiQueryFonts /* Obtain information on Courier font.


( Hpresspace , /* Handle to presentation space.
QF PRIVATE, /* Enumerate private fonts.
"C6urier" ,
/* Font face name.
&Numberstructs /* Number of FONTMETRICS structures returned
(long)sizeof (FONTMETRICS) ,/* Length of structure for EAcii+Sit
&Metrics) ; /* Address of FONTMETRICS structure(s).

xchar = (SHORT)Metrics. IAvecharwidth;


ycharTot = (SHORT)Metrics.IMaxBaselineExt;
ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (F`ontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes.IMatch = Metrics.IMatch;
strcpy (FontAttributes. szFacename,Metrics.szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes. IAvecharwidth = Metrics. IAvecharwidth;
FontAttributes.fsType = FATTR TYPE FIXED;
FontAttributes. fsFontuse = 0;
WinReleaseps (Hpresspace) ;

/*** Get handles to horizontal and vertical scroll bar windows. **************/
HHScroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT , FALSE ) ,
/: :::8:: i:r:::;Tt :/
FID_HORZSCROLL) ; /* Identifier for vertical scroll bar. */
HVscroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT , FALSE ) , /* Handle to parent */
/* window (frame). */
FID_VERTSCROLL) ; /* Identif ier for vertical scroll bar. */
return FALSE;

} /* end Create */

MRESULT EXPENTRY HScroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SHORT Delta; /* Amount to scroll. */

/*** Determine amount to scroll. *****************************************"**/


switc? (SHORT2FROMMP (mp2)) /* Switch on code from scroll bar. */

case SB LINELEFT:
Delta --1;
break;
case SB LINERIGHT:
Delta -1;
break;
case SB PAGELEFT:
Delta --6;
break;

• Figure 4.25..
The source code file for the example program (continued)
UsingscrollBars 191 .

case SB PAGERIGHT:
Delta -6;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -Firstcol;
break;
default:
Delta -0;
break;
)
Delta = max (-Firstcol, min (Delta,FirstcolMax -Firstcol)) ;
/*** Scroll the window if necessary. *****************************************/
if (Delta)
(
/*** Adjust first column value. ************************************/
Firstcol += Delta;
/*** Scroll the window data. ***************************************/
Winscrollwindow
(hwnd, /* Handle of client window.
-Delta * xchar, /* Horizontal scroll amount.
0, /* Vertical scroll amount.
0, /* Must be 0.
0, /* Must be o.
0, /* Must be o.
0, /* Must be o.
SW INVALIDATERGN) ; /* Invalidate "exposed" region.

/*** Force repainting of invalid window region. ********************/


Winup?::#?d°W /* Handle of client window. */

/*** Update the position of the horizontal scroll bar slider. ******/
W±nse:::S:=:::5 , /: g::d::s::i::r:=o::::e::roll bar.

MPFEOM2SHORT (Firstcol,0) , /* Current position.


0) ; /* Second parameter n/a.
)
return FALSE;

} /* end IIScroll */

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Window coordinates, in window coordinates.
SHORT StartLine; /* First file line to paint.
SHORT StopLine; /* Last line to paint.
POINTL Start; /* Starting position to print string.
SHORT LineLength; /* Length of each line displayed.
/*** Get presentation space and coordinates of invalid region in window.

• Figure 4.25..
The source code file for the example program (continued)
• 192 Programmer's Guide to the os/2PresentationManager

Hpresspace = WinBeginpaint
( hwnd , /* Window handle. */
0' /* Handle of PS to have clipping region set. */
&Rect) ; /* Address of struct. to set to invalid region.*/
GpicreateLogFont /* Create a logical font for presentation space*/
( Hpresspace , /* Presentation space handle. */
( PSTR8 ) NULL , /* Logical font name: none. */
ID COURIER, /* Local font ID: define a constant. */
&F6ntAttributes) /* Struct. specifying font from GpiQueryFonts. */
Gpisetcharset /* Make logical font the current character set.*/
( Hpresspace , /* Presentation space handle. */
ID COURIER) ; /* Local font ID. */
/*** Erase invalid region only. **********************************************/

WinFillRect
(Hpresspace, /* Presentation space handle.
&Rect, /* Structure containing window coordinates.
CLR WHITE); /* Color to use (white).

/*** Set color used by 'GpicharstringAt'. ************************************/


Gpisetcolor
(Hpresspace, /* Presentation space handle. */
CLR BIACK); /* Color to use: black. */

/*** Calculate first and last lines to go in invalid region. *****************/


StartLine = TopLine + (ywin - (SHORT)Rect.yTop) / ycharTot;
StopLine = min (LastLine, TopLine + (ywin - (SHORT)Rect.yBottom)
/ ycharTot) ;
/*** Print lines within invalid region. **************************************/
Start.y = ywin -ycharTot * (StartLine -TopLine + 1) + ycharDesc;
Start.x = xchar * (-Firstcol) ;
for (Line = StartLine; Line <= StopLine; ++Line, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue ;
GpicharstringAt * Prints string at given position
( Hpresspace , * Presentation space handle.
&Start' * Structure containing starting position.*
( LONG) LineLength , * Number of characters to print. *
GetLineAddr (Line) ) * Address of line. *
)

WinEndpaint (Hpresspace) ;

return FALSE;

) /* end Paint */

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

• Figure 4.25..
The source code file for the example program (continued)
UsingscrollBars 193 .

/*** Obtain vertical and horizontal dimensions of client window. *************/


ywin = SHORT2FROMMP (mp2) ;
xwin = SHORTIFROMMP (mp2) ;

/*** Update 'TopLineMax' and 'TopLine'. **************************************/

TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;


TopLine = min (TopLine,TopLineMax) ;

/*** Adjust range and position of vertical scroll bar slider. ****************/
WinsendMsg /* Send window message.
(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFEOM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

/*** Enable scroll bar only if needed (TopLineMax > 0) . **********************/


WinEnablewindow
(HVscroll, /* Recipient handle: horizontal scroll bar*/
TopLineMax ? TRUE : FALSE); /* Enable only if max. != 0. */

/*** Update 'FirstcolMax' and 'Firstcol'. ************************************/

FirstcolMax = LINEBUFSIZ - 2 - xwin / xchar;


Firstcol = min (Firstcol, FirstcolMax) ;

/*** Adjust range and position of horizontal scroll bar slider. **************/
WinsendMsg /* Send message.
(HHScroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFROM2SHORT (Firstcol, 0) , /* Position
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range.
return FALSE;

} /* end Size */

MRESULT EXPENTRY Vscroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SHORT Delta; /* Amount to scroll. */

/*** Determine amount to scroll. *********************************************/

switch (SHORT2FROMMP (mp2)) /* Switch on code from scroll bar. */


(
case SB LINEUP:
Delta --1;
break;
case SB LINEDOWN:
Delta -1;
break;

• Figure 4.25..
The source code file for the example program (continued)
• 194 Programmer's Guide to the os/2 Presentation Manager

case SB PAGEUP:
Delta = -ywin / ycharTot;
break;
case SB PAGEDOWN:
Delta = ywin / ycharTot;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -TopLine;
break;
default:
Delta -0;
break;
)
Delta = max (-TopLine, min (Delta,TopLineMax -TopLine)) ;

/*** Scroll the window if necessary. *****************************************/


if (Delta)
(
/*** Adjust top line value. ****************************************/
TopLine += Delta;

/*** Scroll the window data. ***************************************/


Winscrollwindow
(hwnd, /* Handle of client window.
0, /* Horizontal scroll amount.
ycharTot * Delta, /* Vertical scroll amount.
0, /* Must be o.
0, /* Must be o.
0, /* Must be o.
0, /* Must be o.
SW INVALIDATERGN) ; /* Invalidate "exposed" region.

/*** Force repainting of invalid window region. ********************/


Winupdatewindow
(hwnd) ; /* Handle of client window. */
/*** Update the position of the vertical scroll bar slider. ********/
WinsendMsg
(HVscroll, /* Handle to vertical scroll bar. */
:::E8E::?8iT ,T.pLine, o, ,/: :::r:::i::::t::n:lider. :/
0) ; /* Second parameter. n/a. */
)

return FALSE;

} /* end Vscroll */

/*** Buffer- and f ile-management module ***************************************/

#define MAXLINES 4096 /* Maximum number of lines in buffer. */


static struct /* Stores information on each line. */
(
PCH LineAddress ; /* Far address of block containing line. */
unsigned char LineLength /* Length of line (includes \n and \0). */
)

• Figure 4.25..
The source code file for the example program (continued)
UsingscrollBars 195 .

LineTable [MAXLINES] ;

static char LineBuffer [LINEBUFSIZ] /* Temporary line buffer.


static unsigned Lineselector; /* Selector for 'LineBuffer'
static unsigned Lineoffset; /* Offset for 'LineBuffer'.
static SEL Heapselector; /* Selector of heap segment.
void Buflnit (void) /* Initializes the buffer-management module.
(
PCH Farptr;

/* Obtain selector and offset of temporary line buffer.


Farptr = (char far *)LineBuffer;
Lineselector = SELECTOROF (Farptr) ;
Lineoffset = OFFSETOF (Farptr) ;

} /* end Buflnit */

char *ErrorMessage /* Returns a string that describes an error code.


(int ErrorNumber) /* The error code.
(
static char *MessageTable [] =
(
''no error",
''file open failure",
''file too large",
''maximum lines exceeded" ,
"heap memory allocation failed",
''unidentif led error''
in
if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))
ErrorNumber = sizeof (MessageTable) / sizeof (char *) -1;
return MessageTable [ErrorNumber] ;

} /* end ErrorMessage */

int ReadFile /* Reads file into editor.


(char *FileName) /* Name of file.
(
FILE *PtrFile; /* File stream pointer.
long FileLength; /* Size of file.
USHORT Heapsize; /* Size of allocated heap.
NPCH Heapoffset; /* Offset of blocks within heap.
unsigned char LineLength; /* Length of lines.
PCH Farptr; /* Temporary far pointer.
±f ((::::i:e(=R£8:=E);FileNamet"r")) == NULL) /* open the file.

/* Obtain and test file length.


if ((FileLength = filelength (fileno (PtrFile))) == -1)
return (ERROPEN) ;

• Figure 4.25..
The source code file for the example program (continued)
• 196 Programmer's Guide to the os/2 Presentation Manager

if (FileLength > 50000)


return (ERRTOOBIG) ;

/* Make heap 20% larger than file size.


Heapsize = (USHORT) (FileLength + FileLength / 5) ;

HHeap = WincreateHeap /* Allocate a heap for file data.


(0' /* Segment address: 0 means allocate new segment.
Heapsize /* Initial heap size.
0' /* Minimum increase size: 0 means use default.
0' /* Minimum # of dedicated free lists: none.
0' /* Maximum # of dedicated free lists: none.
0\; /* Options: none.
Farptr = WinLockHeap (HHeap) ; /* Get heap segment selector.
Heapselector = SELECTOROF (Farptr) ;

/* Read each line in file into a separate block allocated from heap.
LastLine = -1;
while (fgets (LineBuffer,LINEBUFSIZ-1,PtrFile) != NULL)
* Test for line limit --update 'LastLine'.
f (++LastLine >= MAXLINES)
return (ERRMAXLINES) ;

/* Calculate length of line.


LineLength = (unsigned char)strlen (LineBuffer) + 1;/* Include null*/
/* Insert '\n' into overlength lines. */
if (LineLength == LINEBUFSIZ - 1 &&
LineBuffer [LINEBUFSIZ -3] != '\n')
(
LineBuffer [LINEBUFSIZ -2] = '\n';
LineBuffer [LINEBUFSIZ -1] = '\0';
++LineLength ;
)

/* Allocate a block from heap to hold the line.


Heapof fset = WinAllocMem
(HHeap, /* Heap handle.
LineLength) ; /* Length of line to store.
if (Heapof fset == NULL)
return (ERRALLOC) ;

/* Copy line into heap block. */


movedata (Lineselector,Lineoffset,Heapselector,
(unsigned) Heapof fset , LineLength) ;
/* Insert line information into the table. */
LineTable [LastLine] .LineAddress = MAKEP (Heapselector,Heapoffset) ;
LineTable [LastLine] .LineLength = LineLength;
)

fclose (PtrFile) ; /* Close the file.


return (0) ;

} /* end of ReadFile */

• Figure 4.25..
The source code file for the example program (continued)
UsingscrollBars 197 .

SHORT GetLineLength (int Line) /* Gets length of line in buffer.


(
if (Line < 0 I I Line > LastLine)
return 0;
else
/* Extract line length from table, excluding '\n' and '\0'.
return LineTable [Line].LineLength -2;

} /* end GetLineLength */

PCH GetLineAddr (int Line) /* Gets address of buffer line. */


(
if (Line < 0 I I Line > LastLine)
return NULL;
else
return LineTable [Line].LineAddress;

} /* end GetLineAddr */

/*** Utility functions. ******************************************************/

void ErrorQuit /* Terminate program due to fatal error condition. */


(char *Message) /* Error message to display to user. */
(
char Buffer [60];
sprintf (Buffer,"Program Error: %s",Message) ;
WinMessageBox /* Display a message box.
(ENND DESKTOP, /* Handle of parent: desktop window.
HFrame , /* Handl.e of owner: frame window.
Buffer, /* Message text.
''PM Text Editor", /* Caption.
0' /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB ICONHAND) ; /* Display a hand icon.
Quit (1); /* Call normal termination function.
} /* end ErrorQuit */

void Quit
(int Errorcode) /* Process termination status.
/*
Calls Presentation Manager termination functions and ends program
with specified error code.
*/
(
if (HHeap != NULL)
WinDestroyHeap (HHeap) ;
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue) ;
WinTerminate (HAncBlk) ;
exit (Errorcode) ;
) /* end Quit */

• Figure 4.25..
The source code file for the example program (continued)
I pter five

Controlling th
C:ursor
199.

.I
his chapter adds a cursor to the emerging Presentation
Manager text editor. The cursor serves to mark the cur-
rent z.77scrfz.o71 poz.7if within the file, which is the position
where characters will be either inserted or deleted in
later versions of the program. The code presented in this chapter creates
a cursor and places it initially at the upper left corner of the screen; you
can then use the arrow keys to move the cursor within the window. The
arrow keys thus are no longer used for directly scrolling the file; how-
ever, if you move the cursor beyond the current edges of the window,
the contents of the screen are scrolled to reveal additional file lines or
columns. Thus, the cursor functions indirectly as a scrolling mecha-
nism. This chapter also presents routines for using the Home and End
keys to reposition the cursor at the beginning or end of the line. The
Pgup and PgDn keys, as well as the horizontal and vertical scroll bars,
serve the same function as in the previous version of the program.
In this chapter you will learn how to create, maintain, and move the
cursor. You may be surprised that an entire chapter is required to ex-
plain the logic of the cursor; under the Presentation Manager, however,
managing the cursor is much more complex than in traditional
programming environments, for several reasons. First, you must ex-
plicitly create the cursor each time the client window obtains the input
focus, and destroy the cursor whenever the window loses the focus.
Also, you must adjust the cursor position each time the window chan-
ges size; and finally, you must explicitly reposition the cursor whenever
the user scrolls the window, moves the cursor, or inserts, overwrites, or
deletes characters.
This chapter lists all of the basic routines required to manage the cur-
sor. You can incorporate these additions into the previous version of the
text editor to obtain a program that displays a file and allows you to
move the cursor to any position within this file. The complete listing of
the current version of the example program is given in Figure 6.24, at
the end of Chapter 6. This listing incorporates all of the features dis-
cussed in the current chapter, plus the full keyboard interface and
routines for editing the file that are presented in Chapter 6.
• 200 Programmer's Guide to the os/2PresentationManager

• CREATING THE CURSOR


Since the cursor marks the current position where characters may
be entered from the keyboard, only the window that owns the input
focus should display a cursor. As explained in Chapter 4, the window
with the focus is the one that receives all messages for keyboard input.
A window that employs a cursor, therefore, should create the cursor
each time the window receives the focus, and it should destroy the cur-
sor each time it loses the focus.
Fortunately, the system sends the client window a message,
WM SETFOCUS, each time this window either receives or loses the
focu;. This message is accompanied by a flag (in the parameter mp2),
which is nonzero if the window is receiving the focus and zero if the
focus is being taken away. Remember that the function main calls Win-
SetFocus to explicitly pass the focus to the client window before it
enters the main message loop; therefore, WM_SETFOCUS (with the
receiving flag set) is among the initial messages sent to the client win-
dow immediately after it is created. The initial messages processed by
the example program are sent in the following order:

1. WM CREATE
2. WM SIZE
3. WM SETFOCUS (mp2 is set, indicating that the focus is being
recei-ved)
4. WM PAINT

Subsequently, the system sends the WM_SETFOCUS message when-


ever the user either changes the focus to another window (for example,
by selecting another application with the Alt-Esc key or by clicking on
another window with the mouse), or restores the focus to the client win-
dow. The WM_SETFOCUS message is explained in Figure 5.1.
The example program processes the WM_SETFOCUS message in the
function SetFocus, listed in Figure 5.2. The basic logic of this routine is
simple: if the focus is being gained, it creates a cursor, and if the focus is
being lost, it destroys the cursor.
SetFocus creates the cursor by calling the Wincreatecursor Presen-
tation Manager function (Figure 5.3). The program passes the handle
Controllingthecursor 201 .

WM SETFOCUS
Purpose..
Sent by the system to a window whenever it is about to
receive or lose the input focus.

Parameters..
mJ- xpl If the focus is being received, contains the
handle of the window that previously
owned the focus, or NULL if no
window owned the focus. If the focus is
being lost, contains the handle of the
window that is receiving the foous, or NULL
if no window is receiving the focus.
reAEun xp2 TRUE if the window is rccc!.z7{.7tg the focus, or
FALSE if the window is Jos!.7ig the focus.

Return Value ..
FALSE.

• Figure 5.1..
The WM_SETFOCUS Presentation Manager message

hwnd as the first parameter so that the cursor will be displayed within
the client window. The second two parameters specify the initial posi-
tion of the cursor with respect to this window. These values are given in
pixel coordinates, which are the same units used to specify the dimen-
sions of the window, the metrics of the character font, and the starting
positions of strings printed within the window. The cursor-position
coordinates specify the location of the lower left pixel of the cursor.
Note that these values specify a position within the standard window
coordinate System illustrated in Figure 3.27, in which the origin (the
position x=0, y=0) is at the lower left corner of the window.
The program maintains two global variables, CursorLine and
Cursorcol, which store the current row and column position of the
character associated with the cursor (which is displayed immediately to
the right of the cursor; the cursor shape and position will be explained
shortly). Note that the row and column positions in CursorLine and
• 202 Programmer's Guide to the os/2 Presentation Manager

MRESULT EXPENTRY SetFocus (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** If client window is RECEIVING focus, create cursor. *********************/
if (LONGFROMMP (mp2))
(
Wincreatecursor /* Create a new cursor.
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position
0' /* x size of cursor: nominal border.
ycharTot, /* y size of cursor.
CURSOR SOLID /* Solid cursor.
CURSOR-FIASH /* Flashing cursor.
NULL) ; /* Clipping rectangle: entire window.
/*** Make the cursor visible. *******************************************/
Winshowcursor
(hwnd, /* Client window handle. */
TRUE) ; /* Show it! */
)
/*** If client window is LOSING focus, destroy the cursor. *******************/
else
WinDestroycursor (hwnd) ;

return FALSE;

} /* end SetFocus */

• Figure 5.2..
The function SetEocus of the example program

Cursorcol refer to the location of the associated character zt7z.£fez.71 ffec ¢.Zc
Z7##er, and not the character's position within the window. These two
variables are initialized to 0, so that the cursor is initially associated
with the first character in the file (rows and columns within the file are
numbered beginning with 0). Since the position of the cursor on the
screen passed to Wincreatecursor must be specified in pixel units, the
row and column positions are converted to absolute pixel coordinates
within the window. The horizontal coordinate is calculated using the
expression

(Cursorcol - Firstcol) * xchar

and the vertical coordinate is calculated with the expression

ywin - (CursorLine - TopLine + 1) * ycharTot


Controllingthecursor 203 .

Note that these expressions yield the window coordinates of the


lower left corner of the corresponding file character (bcJozu the baseline).
The next two parameters (cx and cy) give the width and height of the
cursor, also in pixel units. By passing a value of 0 for the horizontal
dimension, the program specifies the 7io777!.73¢J sysfcm border zt7!.dffe, which

Wincreatecursor
Purpose..
Creates a cursor within the specified window.

Prototype..
B00L APIENTRY Wincreatecursor
(Hue hund, Handle of window to have the cursor.
SHORT x, Horizontal position of cursor within the
window.
SHORT y, Vertical position of cursor within the
window.
SHORT cx, Width of cursor; 0 means to use the
nominal system border width.
SHORT cy, Height of cursor; 0 means to use the
nominal system border height.
USHORT fs, The cursor style; you may combine one or
more of the fonowing values:

Value Meaning
CURsOR SOLID Solid oursor
CURsOR HALF- Halftone cursor
TONE
curoR RECT Solid rectan-
gular cursor
CURSOR FRAME Rectangular
frame cursor
CURsOR FLASH Blinking oursor

• Figure 5.3..
The WincreaLtecursor Presentation Manager function
• 204 Programmer's Guide to the os/2 Presentation Manager

CURsOR SETPOS Sets a new our-


sor position (as-
sumes that a
oursor has al-
ready been
created); causes
function to ig-
nore all other
styles and the cx
and cy
parameters

PRECTL prclclip) ,. Points to a RECTL structure (defined in


Figure 2.22) containing the dimensions of
a rectangle within which the cursor is
visible (a clipping reetangle); if the cursor
moves outside this rectangle, it becomes
invisible. A value of NULL sets the
cnpping rectangle to the entire
dimensions of the window.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
When the cursor is first created it is invisible; you must call
Winshowcursor to make it visible. A window should create
a cursor whenever it receives the focus, and it should destroy
the cursor (WinDestroycursor) whenever it loses the focus.

RelatedFunctions..
WinDestroycursor (Figure 5.6)
Winshowcursor (Figure 5.5)

• Figure 5.3..
The WLriclea;tecursor Presentation Manager f unction ( continued)
Controllingthecursor 205 .

is a system-defined value (SV_CXBORDER) that yields a narrow


but easily visible cursor. The program passes a height value of ychar-
Tot so that the cursor is given the maximum character height.
The next parameter-rgf, the cursor style-is assigned the value
CURSOR_SOLID, for a solid rectangular cursor, combined with
CURSOR_FLASH, for a blinking cursor.
The resulting cursor is a narrow, blinking vertical bar, displayed at
the left edge of the cell containing the associated character (which has a
width of xchar and a height of ycharTot). Since the cursor is narrow, it
falls totally within the area of this rectangle reserved for the blank space
between characters, and does not overlap the pixels used to form nor-
mal alphanumeric characters. Consequently, the cursor appears on the
screen as a vertical bar Z7cfwcc71 two characters. As explained, the file
coordinates CursorLine and Cursorcol refer to the character to the right,
which in this book is termed the associated character. In subsequent ver-
sions of the program, the Del key win erase the associated character to the
right of the cursor, leaving the cursor in its present position; the Backspace
key will delete the character to the left and move the cursor one space left;
and a new character entered from the keyboard win be inserted to the left,
causing the oursor to move one space right. Figure 5.4 illustrates the cursor
and its relation to the sulTounding characters.
The cursor used by the example program thus differs from conven-
tional cursors, which either underlie the associated character or high-
light the entire area occupied by this character. The program cursor
conforms to the Presentation Manager concept of a cursor as a marker
indicating an insertion point rather than a character; in fact, the
documentation often refers to the cursor as a c¢rc£, which is a
proofreader's symbol typically placed Z7cfzucc7i characters.
A 7iofc rcg¢rd3.7ig sfyJc.. The cursor is an example of a Presentation
Manager feature that can be created using a wide variety of styles. The
developers of the Presentation Manager, however, have defined a set of
application style guidelines that recommend which of the many pos-
sible design options should be selected for particular situations. It is
wise to conform to the standard style, since one of the primary benefits
of Presentation Manager programs is that they provide a uniform-and
therefore easily learned-user interface. This book follows these
guidelines whenever practical; accordingly, the strong resemblance be-
tween the example program and standard Presentation Manager and
• 206 Programmer's Guide to the os/2 Presentation Manager

Windows applications (such as the Windows Notepad editor) is neither


coincidence nor blind imitation. (See the Microsoft Windows AppJz.c#£z.o#
Sfyzc G#z.dc, cited in the Bibliography.)
The program cursor created by the call to Wincreatecursor has all
the desired attributes, except that it is not yet visible. To make the cursor

• Figure 5.4..
The cursor created by the exanple progran
Controllingthecursor 207 .

visible, the program calls the function Winshowcursor (Figure 5.5),


passing a value of TRUE as the second parameter (you can assign a
value of FALSE to temporarily hide a visible cursor).
Finally, if the client window is Josl.77g the focus (mp2 is zero), Set-
Focus destroys the cursor formerly created by Wincreatecursor. The
cursor is destroyed by calling the Presentation Manager function Win-
Destroycursor (Figure 5.6), passing it the handle of the associated win-
dow (hwnd, the client window).

Winshowcursor
Purpose..
Makes visible or hides the cursor associated with the
specified window.

Prototype..
BOOL APIENTRY Winshowcursor
(HWND hwnd, Handle of the window owning the cursor
(created by calling Wincreatecursor).
BooL fshow) ,. A value of TRUE causes the function to
make the cursor visible, and a value of
FALSE causes it to hide the cursor.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Related Functions ..
Wincreatecursor (Figure 5.3)

• Figure 5.5..
The Winshowculsor Presentation Manager function
• 208 Programmer's Guide to the os/2PresentationManager

WinDestroycursor
Purpose..
Destroys the cursor associated with the specified window.

Prototype..
BOOL APIENTRY WinDestroycursor
(HWND hwnd) ,. Handle of the window owning the cursor
(created by calling Wincreatecursor).

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Related Functions ..
Wincreatecursor (Figure 5.3)

• Figure 5.6..
The W±nDestrayculsor Presentation Manager function

• MAINTAINING THE CURSOR


Not only must the program create the cursor each time the win-
dow gains the focus and destroy it when it loses the focus, but it must
also maintain the cursor as the window changes size. This section
describes the routines for maintaining the cursor that are added to the
function Size, which processes the WM_SIZE message sent by the sys-
tem whenever the dimensions of the window change.

Keeping the Insertion Point


within the Window
When you 7'cdt/cc the size of the window, it is quite possible for the
character associated with the cursor to fall outside the block of file data
currently displayed within the window. This chapter adds a routine to
Controllingthecursor 209 .

the Size function that automatically scrolls the file data, if necessary, so
that the insertion point always remains visible within the window. This
code is listed in Figure 5.7; note that the flag Update is defined and ini-
tialized within the Size function as follows:

int Update = 0,.

The routine first determines whether the line containing the cursor
(CursorLine) falls bcJozu the last line visible in the window. If this condi-
tion is true, it adjusts the top line displayed in the window (TopLine) so
that CursorLine falls just inside the lower window boundary. Similarly,
the program tests whether the cursor falls to the ri.gfef of the visible por-
tion of the file, adjusting Firstcol if necessary. If either of these adjust-
ments is made (indicated by setting the Update flag), the program
explicitly invalidates the entire window by calling the Presentation
Manager function WinlnvalidateRect (Figure 5.8).
Invalidating a region of a windowutr the entire window-through
the WinlnvalidateRect function causes the system to send a
WM_PAINT message to the window procedure to give it an oppor-
tunity to repaint the invalid area. As described in Chapter 4 (in the sec-
tion on The WM_HSCROLL Message), this function provides a slow

/*** Scroll window if necessary so that cursor position is visible. **********/


if (CursorLine >= TopLine + ywin / ycharTot)
(
TopLine = CursorLine -ywin / ycharTot + 1;
Update -1,
)
if (Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = Cursorcol -xwin / xchar + 1;
Update -1;
)
if (Update)
WinlnvalidateRect
( hwnd ' /* Client window handle.
0, /* Rectangle: 0 means whole window.
FALSE) /* Do not automatically include children

• Figure 5.7..
The routine for keeping the insertion point within the window
• 210 Programmer's Guide to the os/2 Presentation Manager

WinlnvalidateRect
Purpose..
Adds a rectangular area to a window's update region.

Prototype..
BO0L APIENTRY WinlnvalidateRect
(IIWND hwnd, Handle of the window to have
its update region modified.
PRECTL prcl , Pointer to a RECTL structure
containing the coordinates of
the rectangle to add to the
window's update region (the
RECTL structure is defined in
Figure 2.22); a value of NULL
means to invalidate the entire
window.
BOOL flncludechildren) ,. If this flag is TRUE, the
function will always include
descendants of hwnd in the
invalid region; if FALSE, the
function will include
descendants in the invalid
region unless the window was
created with the
WS_CLIPCHILDREN style.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
Invalidating a region of a window will cause the system to
send a WM_PAIP\IT message to give the window the oppor-
tunity to repaint this region.

• Figure 5.8..
The WLnlrIv al±dateRect Presentation Manager f unction
Controllingthecursor 211 .

but simple mechanism for scrolling the contents of the window. Since
resizing operations are not performed in rapid succession like scrolling
operations when you hold down an arrow key, the speed of this ap-
proach is sufficient for the Size function.

Recreating the Cursor


When the program creates a cursor, it specifies a location within
the window where the cursor is to be displayed. Each time the window
changes size, the system dutifully maintains the cursor at this s¢77zc win-
dow location. Remember, however, that the cursor coordinates are
specified with respect to the Jozucr left comer of the window; in contrast,
the text displayed within the window is always aligned with the I/ppcr
left corner. Consequently, when the window is reduced in height, the
vertical window coordinates of all characters still visible within the
window are diminished by the amount of the window reduction so that
the characters remain the same distance from the top of the window.
Since the cursor coordinates remain the same, the cursor no longer ap-
pears next to its associated character after the window is resized.
Accordingly, the routine that processes the WM_SIZE message (the
function Size in the example program) must recalculate the cursor coor-
dinates for the new window size, and reposition the cursor by calling
the function Wincreatecursor (as you will see in the next section, you
can call Wincreatecursor not only to create a new cursor, but also to
resize an existing cursor). However, another problem remains: the cur-
sor czi.ppl.7zg recf¢71gJc. The cursor clipping rectangle is the region of the
window within which the cursor is visible, and it is specified by the last
parameter (prclclip) passed to Wincreatecursor. If desired, you can
set this rectangle to a subregion of the associated window. The user can
freely move the cursor outside of the clipping rectangle; however, doing
so will make the cursor invisible until it is brought back within the clip-
ping rectangle.
The example program assigns a value of NULL to the clipping rec-
tangle parameter. This value causes Wincreatecursor to set the clip-
ping region to the current dimensions of the entire window. Note,
however, that if the window size is enlarged, the clipping rectangle
remains the same, and thus becomes a subregion of the newly sized
• 212 Programmer's Guide to the os/2 Presentation Manager

window. If the user subsequently moves the cursor into the new area of
the window, it will inexplicably disappear.
The solution to both problems is for the WM_SIZE routine to com-
pletely destroy the existing cursor and then recreate the cursor, specify-
ing the new cursor location and a clipping region that is the size of the
current window (by passing NULL as the clipping rectangle
parameter). The code required to perform these steps is listed in Figure
5.9; this code is added to the Size function of the example program,
which processes the WM_SIZE message.
Note, however, that before destroying and recreating the cursor, the
program calls the Presentation Manager function WinQueryFocus (Fig-
ure 5.10) to determine whether the client window currently has the
focus. WinQueryFocus returns the handle of the current focus window.
The program destroys and recreates the cursor only if this handle
matches the handle of the client window, hwnd; otherwise, there is no
cursor associated with the client window (the cursor will be properly

/*** If client has focus, must RE-CREATE the cursor for new size. ************/
if (hwnd == WinQueryFocus /* Does client have focus?
iAF!gET?ESKToP , / : E:s:ogiT:c!e:f:3:w?andle.
(
/*** Destroy existing cursor. *******************************************/
WinDestroycursor (hwnd) ;

/*** Create new cursor. *************************************************/


Wincreatecursor /* Create a new cursor. */
{E¥=S6rcoL _ F±rstcoL, * £:h::;ent 7±ns°go:::€:a.of cursor. :,
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position. */
0, /* x size of cursor: nominal border. */
ycharTot , /* y size of cursor. */
CURSOR SOLID /* Solid cursor. */
CURSOR-FljASH, /* Flashing cursor. */
NULL) ; /* Clipping rectangle: entire window.*/
/*** Display the cursor. ************************************************/
Winshowcursor
(hwnd, /* Client window handle. */
TRUE) ; /* Show it! */
)

• Figure 5.9..
The routine in the function Size for recreating the cursor
Controllingthecursor 213 .

recreated through the SetFocus function when the client window


regains the focus).
The routine in Figure 5.7 recalculates the cursor coordinates from the
appropriate global program variables (Cursorcol, xchar, and others),
usingthesameexpressionsemployedbytheSetFocusfunctionlistedin
Figure 5.2 and described previously in the chapter. In fact, all the
parameters are the same as those passed by the function SetFocus;
however,theeffectofpassingthevalueNULLfortheclippingrectangle
is to set this region to the 71czu size of the client window, as desired.

WinQueryFocus
Purpose..
Obtains the handle of the focus window.

Prototype..
HWND APIENTRY WinQueryFocus
(HWND hundDesktop, The handle of the desktop window;
you must assign the value
HWND DESKTOP.
BcoL fLock) ,. Lock indicator: if TRUE, the function
will lock the window (a locked
window cannot be destroyed); if
FALSE, the window will not be locked.

Return Value ..
The handle of the focus window, or NULL if there is no focus
window.

• Figure 5.10..
The WinQueryF oc:us Presentation Manager f unction

• MOVINGTHECURSOR
The two previous sections have shown how to create the cursor and
how to maintain the cursor in proximity with its associated character in
• 214 Programmer'sGuideto the os/2Presentation
Manager

the window. This section describes two situations in the current version
of the example program in which the cursor is moved to another char-
acter (as you will see, moving the cursor to another associated character
does not necessarily change the cursor position with respect to the win-
dow). First, pressing an arrow key, or the Home or End key, directly
repositions the oursor on another character. Second, the cursor is moved
to another character when the window is scrolled using a scroll bar or
the Pgup or PgDn key. (The window may also have to be scrolled when
the cursor is moved beyond the visible section of the file with the arrow,
Home, or End key.) Chapter 6 will describe the movement of the cursor
that occurs when you enter or delete characters in the file.

The Cursor-Movement Keys


The current version of the example program uses the four arrow
keys and the Home and End keys for directly moving the cursor (unlike
the previous version, which used the arrow keys to scroll the window).
As explained in Chapter 4, these keys are among those identified by zJz.r-
£t/¢J key codes (used primarily to label keystrokes that do not have an
ASCII value). Remember that the previous version of the program
processed messages for the arrow and Home/End keys by passing
these messages directly to the appropriate scroll bar control window
(which then sent scrolling messages back to the client window). In the
current version, however, the client window procedure processes these
messages itself, without passing them through the scroll bar window
procedures. (Note that the term cJ!.c77£ zt7z.7idozu proced#rc is used in a
general sense to include not only the registered function, Wndproc, but
also all functions, such as Character and VirtKey, called by Wndproc.)
In the current version of the program, all virtual keys (such as the
cursor-movement keystrokes) are processed in the function VirtKey.
VirtKey is caned by the client window procedure when it receives a
WM_CHAR message for a virtual key. The manner in which a virtual
keyisrecognizedandthemacrousedtoextractthecodesforvirtualkeys
will be explained in Chapter 6, which describes the complete keyboard
interface.
Controllingthecursor 215 .

The Arrow Keys


The routine for processing the arrow keys is listed in Figure 5.11
(this routine is part of the function VirtKey). Each of these keys is used
to move the cursor one row or column in the corresponding direction.
Ifthekeyisa1key(theVK_UPcase),theprogramfirsttestswhether
the cursor is currently at the top line of the window. If the cursor is at
the top of the window, the program needs to scroll the window up one
row. Note that scrolling the window one row up is exactly the same task
that is performed by the window procedure whenever it receives the
WM_VSCROLL message, with an SB_LINEUP code. Therefore, rather
than duplicating the scrolling routine within the function VirtKey (or
sequestering this routine away in yet another subroutine), the program
s±rLplysend-stheappropriatemessagetoitself."ep_rggranse.ndst:risr±_=s-
sage by calling the WinsendMsg Presentation Manager function (Fig-
ure 4.8), specifying hwnd (the client window's own handle) as the
targetwindow.ThemessageidentifierisWM_VSCROLL,andthehigh-
order word of mp2 is set to SB_LINEUP. Accordingly, when the system
sends this message, control passes to the routine for scrolling up one
row, which is within the Vscroll function (to be described later in the
chapter).
This is the first of many examples of the client window procedure
sending a message to itself, an important technique that deserves a
smau digression. Note that the WinsendMsg function causes the sys-
tern to directly invoke the client window procedure (the message is 7to£
placed in the message queue). Therefore, if a window procedure directs
a message to itself, the system generates a rcc#7's!.z7e call to the window
procedure (a recursive call refers to a body of code reentering itself as a
subroutine). When this recursive call completes, control returns to the
original invocation of the window procedure. Recursive calls can also
occur in other situations; for example, a call to WinDefwindowproc
(Figure 2.17) may result in another message being sent back to the client
window. In general, therefore, you must write all window procedure
code with the possibility of recursive calls in mind. Accordingly, tern-
porary variables that must be duplicated for each invocation of the pro-
cedure should be declared as ¢#£om¢fl.c variables. (Automatic variables
are those declared within the scope of a function, 7iof using the static
keyword; these variables are placed within the procedure stack frame,
which is distinct for each recursive call of the function. An automatic
• 216 Programmer's Guide to the os/2Presentation
Manager

/*** Process up-arrow key. *********************"*************„********/


case VK UP:

/*** If cursor at top of window, scroll up. ************************/


1, f (CursorLine
if /^1,,-__`.T -.__= -__ -.
TOpLine) ,
(
WinsendMsg /* Scroll window one line up. */
(hwnd,
" VSCROLL,
OL,
MPFROM2SHORT (0,SB LINEUP) ) ;
return TRUE;
)
/*** If cursor NOT at top, simply adjust 'CursorLine'. *************/
else
--CursorLine ;
break;
/*** Process down-arrow key. **************************"*****"*********/
case VK DOWN:

/*** If cursor at end of file, simply return. **********************/


if (CursorLine == LastLine)
return TRUE;

/*** If cursor is in bottom line of window, scroll down. ***********/


else if (CursorLine == Topljine + ywin / ycharTot - 1)
(
WinsendMsg
( hwnd ,
" VSCROLL,
OL,
MPFROM2SHORT (0,SB LINEDOWN) ) ;
return TRUE;
)
/*** Otherwise, simply adjust 'CursorLine'. ************************/
else
++CursorLine ;
break;
/*** Process left-arrow key. ********************************************/
case VK LEFT:

/*** If cursor is at left of window, scroll left. ******************/


if (Cursorcol == Firstcol)
(
WinsendMsg
( hwnd ,
WM HSCROLL,
OL,
MPFROM2SHORT (0,SB LINELEFT) ) ;
return TRUE;
)
/*** Otherwise, simple adjust 'Cursorcol'. *************************/
else

• Figure 5.11..
The routine for processing arrow keys
Controllingthecursor 217 .

--Cursorcol ;
break;
*******************************************/
/*** Process right-arrow key.
case VK RIGHT:

/*** If cursor is at right of window, scroll to right. *************/


if (Cursorcol == Firstcol + xwin / xchar - 1)
(
WinsendMsg
( hwnd ,
WM HSCROLL,
OL'
MPFROM2SHORT (0,SB_LINERIGHT) ) ;
return TRUE;

/*** Other*ise, simply adjust 'Cursorcol'. *************************/


else
++Cursorcol ;

break;

• Figure 5.11..
The routine for processing arrow keys (continued)

variable can also be located at the SI or DI machine register; separate


values are maintained for these registers for each function invocation.)
For example, a local flag such as Update, used by the function VirtKey,
should be an automatic variable. In contrast, variables that are to be
shared by all invocations of a function should be declared as static, or
declared outside of the function scope (cxfer7i¢J variables, required
when more than one function must use the variable). For example,
CursorLine is declared as an external variable so that it can be shared
directly by any invocation of any function.
If the cursor is 77of within the top line of the window, the routine for
the VK_UP case simply decrements CursorLine and issues a break
statement. When this routine-r any of the other routines that handle
the arrow or Home/End keys-issues a break statement, control trans-
fers to a call to Wincreatecursor, listed in Figure 5.12. Note that this
function call passes a style value of CURSOR_SETPOS (as the sixth
parameter, fs); this value causes the function to reposition an existing
cursor rather than create a new cursor. When you specify CUR-
SOR_SETPOS, the function ignores any other style values that you may
• 218 Programmer'sGuidetothe os/2Presentation
Manager

/*** Update cursor position for all cases above that altered 'Cursorl.ine' or
'Cursorcol'. ************************************„***************************/

wincr:::::Trsor /: S::e::s:::::wo:a:::::r.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position.

;i::9? sETPoS ' j; iEij;ini:r:ii:iii:ii;;aon|y.

• Figure 5.12..
The call to Wincreatecursor for updating the cursor position

unwittingly include, as well as the cursor size dimensions (the fourth


and fifth parameters, cx and cy). When the program calls Wincreate-
Cursor, the new value of CursorLine causes the system to move the
cursor up one line.
The routine for the down-arrow case (VK_DOWN) performs a
similar task, scrolling the window one line down if the cursor is on the
bottom line in the window, or simply decrementing CursorLine and is-
suing a break statement if the cursor is above the last line. In the same
manner as the up-arrow case, the break statement passes control to the
call to Wincreatecursor, listed in Figure 5.12, which serves to move
the cursor one line down. Note, however, that the down-arrow routine
returns immediately if the cursor is already on the last line in the file
(LastLine, which might not be the bottom of the window).
The routines for the L and i keys (VK_LEFT and VK_RIGHT) work
in a manner exactly analogous to the routine for the up-arrow and
down-arrow cases.

The Home and End Keys


The Home and End keys serve to move the cursor to the begin-
ning or the end of the current line. The branches of the switch statement
that handle these keys are listed in Figure 5.13.
The routine that processes the Home key (VK_HOME) simply sets
Cursorcol to 0 and branches to the call to Wincreatecursor (by is-
suing a break statement) to move the cursor to the first column. Note,
Controllingthecursor 219 .

/*** Process Home key. **************************************************/


case VK HOME:

/*** Scroll if beginnings of lines not visible. ********************/


if (Firstcol != 0)
(
WinsendMsg /* Send scroll to absolute position */
/* message to self. */
( hwnd ,
WM HSCROLL,
OL'
MPFROM2SHORT (0, SB_SljlDERPOSITI0N) ) ;
)

Cursorcol = 0;
break;
/*** Process End key. ***************************************************/
case VK END:

/*** Set temporary cursor position to end of line. *****************/


Newcursorcol = (int)GetLineLength (CursorLine) ;

/*** Clear update flag. ********************************************/


Update -0;

/*„ End of line to right of portion visible in window. ************/


if (Newcursorcol > Firstcol + xwin / xchar - 1)
(
NewFirstcol = Newcursorcol -xwin / xchar + 1;
Update -1;
)
/*** End of line to left of portion visible in window. **************/
else if (Newcursorcol < Firstcol)
(
NewFirstcol = Newcursorcol ;
Update -1;
)
/*** Scroll window if end of line not visible. *********************/
if (Update)
WinsendMsg
( hwnd '
WM HSCROLL,
OL,
MPFROM2SHORT (NewFirstcol ,
SB SLIDERPOSITION) ) ;

/*** Set permanent cursor column position. *************************/


Cursorcol = Newcursorcol;
break;

• Figure 5.13..
The routines for processing the Home and End keys
• 220 Programmer's Guide to the os/2 PresentationManager

/*** Proce=_=_ Page TJp key. ***********************************************/


case VK PAGEUP:
WiHsendMsg /* Send scroll page up message to self . */
(hwnd
" VSCROLL,
OL,
MPFROM2SHORT (0,SB PAGEUP) ) ;
return TRUE;

/*** Proce=_5_ P_?q_e__Pp_yn key. *********************************************/


case VK PAGEDOWN:
WiHsendMsg /* Send scroll page down message to self . */
(hwnd
WM VSCROLL,
OL,
MPFROM2SHORT (0,SB PAGEDOWN) ) ;
return TRUE;

• Figure 5.13..
The routines for processing the Home and End keys (continued)

however, that in keeping with the philosophy that the cursor position
should always be visible within the window, the routine scrolls the win-
dow to the far left if the new cursor position would fall outside the cur-
rently visible range of the file lines (in other words, if Firstcol is not
equal to 0). As in the arrow-key routines, the window procedure easily
generates the appropriate scrolling action by sending a WM_HSCROLL
message to itself, via the WinsendMsg function. Note, however, that
the accompanying action code is set to SB_SLIDERPOSITION (in the
high-order word of mp2), which specifies an absolute position (0,
placed in the low-order word of mp2); the resulting message is the same
as that generated when the user moves the horizontal scroll bar slider to
the beginning of its range.
The Home-key routine concludes with a break statement, which pas-
ses control to the Wincreatecursor function call (listed in Figure 5.12)
to move the cursor to its new position.
The logic for the End key is similar to that for the Home key, but is slight-
ly more complex because the new cursor position (at the end of the dis-
played line) may be either to the right or to the left of the block of file data
Controllingthecursor 221 .

currently displayed in the window. The routine tests for both of these
conditions; if either condition is true, it performs the fouowing actions:

• It calculates a new value for Firstcol that would bring the cursor
just into the visible portion of the window (if the cursor falls to
the right of the window, it is moved to the right edge within the
window; if it falls to the left, it is moved into the window at the
left edge). Note, however, that the new value is ziof assigned to
Firstcol, but is held in the temporary variable NewFirstcol (the
reason will be explained later).
It sets the Update flag, indicating that the window must be
scrolled either right or left.

If the Update flag is set, the program then scrolls the window
horizontally by sending a message to itself, in the same manner as the
Home-key routine, except that the absolute position is specified as
NewFirstcol. Note that you cannot assign the value held in NewFirst-
Col directly to the global variable Firstcol before calling the scrolling
routine, because this routine calculates the new value of Firstcol Z7¢scd
t4po# ffee /or77zer zJ¢Jt4c of ffee z7fl7'i.¢Z7Zc (which must therefore be left intact).
Finally, whether or not the window requires scrolling, the End-key
routine assigns the appropriate new value to Cursorcol to place the
cursor at the end of the line (this value was obtained from the buffer
module function GetLineLength and was stored in the temporary vari-
able Newcursorcol). The routine then issues a break statement so that
control will pass to the call to Wincreatecursor that moves the cursor.

Moving the Cursor When Scrolling


As in the previous version of the example program, the scrolling
messages (WM_HSCROLL and WM_VSCROLL) are handled by the H-
Scroll and Vscroll functions. The current versions of these functions,
however, must contain additional logic to maintain the correct position
of the cursor within the window. Before describing this logic, however,
this section summarizes the various methods by which scrolling mes-
sages are generated in the example program.
• 222 Programmer's Guide to the os/2Presentation
Manager

Generation of Scrolling Messages


In the current version of the example program, the messages
WM_VSCROLL and WM_HSCROLL are sent to the client window
under the following circumstances:

• As seen in the previous section, scrolling messages are sent by


the routines that process the cursor-movement keys (that is, the
arrow, Home, and End keys) whenever these keys move the cur-
sor to a point that is outside the section of the file currently dis-
played within the window.
• In the same manner as the previous version of the program, the
scroll bars send scrolling messages whenever they receive
relevant mouse input.
• The virtKey function sends the wM_VSCROLL message in
response to the Pgup or PgDn key.

/*** Prc>cess
'case Page Up key.
VK PAGEUP: ***********************************************/

WinsendMsg /* Send scroll page up message to self . */


(hwnd
WM VSCROLL,
OL,
MPFROM2SHORT (0,SB PAGEUP) ) ;
return TRUE;

/*** Process Page Down key. *********************************************/


case VK PAGEDOWN:
WiHsendMsg /* Send scroll page down message to self . */
(hwnd
" VSCROLL,
OL,
MPFROM2SHORT (0,SB PAGEDOWN) ) ;
return TRUE;

• Figure 5.14..
The routine for processing the Pgup and PgDn keys
Controllingthecursor 223 .

The routine for processing the Pgup and PgDn keys (which is con-
tained in the routine VirtKey) is listed in Figure 5.14. In these two
branches of the switch statement, the window procedure simply sends
itself a WM_VSCROLL message, accompanied by either the
SB PAGEUP or SB PAGEDOWN action code.

Maintaining the Cursor When Scrolling


As you have seen, the HScroll and Vscroll functions scroll the
window in the appropriate direction by calling the Winscrollwindow
function. Winscrollwindow, however, is slightly overzealous and
scrolls not only the window data, but also the cursor image. The ex-
ample program is designed to maintain the cursor in the s¢77ic relative
position with respect to the window each time the window is scrolled
(which causes a shift in the character associated with the cursor). There-
fore, the HScroll and Vscroll functions must contain instructions to
place the cursor back in the same window position after the window is
scrolled. (These routines also need to update the global variables
Cursorcol and CursorLine, which change each time the window
is scrolled.)
To maintain the cursor in the same relative position with respect to
the window, HScroll performs the following tasks in addition to those
performed in the previous version of this function:

• Once the number of columns the window is to be scrolled


(Delta) has been calculated, the routine uses this quantity to cal-
culate the new value of Cursorcol, as follows:
Cursorcol += Delta,.
Note that the s¢77zc quantity (Delta) is added to both Firstcol and
Cursorcol, thus keeping the cursor in its same horizontal posi-
tior\ with respect to the window .

Before scrolling the window, the routine calls the function Win-
Showcursor (Figure 5.5), passing a value of FALSE as the
second parameter to hide the cursor. Making the cursor invisible
before scrolling prevents the unpleasant visual effect as the cur-
sor scrolls away from the window edge and then is moved back
to the edge when you repeatedly scroll the window by holding
• 224 Programmer's Guide to the os/2 PresentationManager

down the arrow key (the cursor appears to hammer against the
edge of the window).
At the end of the HScroll function, Wincreatecursor is called to
restore the cursor to its appropriate window location. The func-
tion call is the same as that listed`in Figure 5.12.
• Immediately before returning, HScroll calls winshowcursor
once again, this time passing TRUE as the second parameter to
make the cursor reappear.

The Vscroll function performs these same additional tasks, except


that it updates the variable CursorLine rather than Cursorcol.

• CONCLUSION
A MAKE file for the current version of the example program is
listed in Figure 6.22, and the definition file in Figure 6.23. Figure 6.24
provides a complete program listing that contains all of the features dis-
cussed in this chapter as well as in Chapter 6.
The routines presented in this chapter have added a cursor to the ex-
ample program. Since the cursor marks the current insertion point
within the file, the next logical step is to allow you to begin inserting
characters. Chapter 6 adds a complete keyboard interface to the ex-
ample program, which permits you to enter new characters as well as
delete existing characters.
227.

.I
he version of the Presentation Manager text editor pre-
sented in this chapter finally allows you to edit the con-
tents of the file. (You should not invest too much time
changing the file, however, since you will not be able to
save these changes until the version of the program given in Chapter 7!)
You can type characters directly into the file at the insertion point
marked by the cursor created in Chapter 5, and you can insert new lines
by pressing the Enter key. You can also delete individual characters
with the Del and Backspace keys, or delete entire lines by pressing F9.
The program supports both overwrite and insert modes, and permits
you to edit an existing file or start a new file.
In this chapter, you will learn how to interpret keyboard messages
sent to the client window; you will learn how to process normal charac-
ter keys, as well as the keys identified by virtual codes (such as function
or arrow keys); and you will learn how to manipulate the data struc-
tures containing the file data in order to modify the contents of the file.
The new features of the example program discussed in this chap-
ter reside in the window procedure subroutines that process the
WM_CHAR message, and in the buffer-management module. The
character-handling routines now process most of the keyboard mes-
sages, rather than simply ignoring the majority of keyboard input.
These routines are supported by eight new functions in the buffer-
management module for inserting and deleting characters and lines.
The discussions in this chapter focus on the routines of the window pro-
cedure, which illustrate techniques unique to the Presentation Manager.
A lengthy discourse on the more conventional code within the buffer-
management module would be a digression from the primary topic of
this book; therefore, the chapter clearly illustrates the purpose of each
of these functions when they are first encountered, but discusses only
the most salient points of their implementation.
The complete listing of the current version of the example program is
given in Figure 6.24, at the end of the chapter.

• THEWM CHARMESSAGE
Whenever a key is either pressed or released, the Presentation
Manager records the event by placing an entry in a single keyboard
• 228 Programmer's Guide to the os/2PresentationManager

buffer known as the sysfc77z qt/cwc. This queue is large enough to store
approximately 60 keyboard events, and thus allows you to type keys
well ahead of the processing of these keys by the active application. The
Presentation Manager dispenses with the entries in the system queue by
sending WM_CHAR messages, one at time, to the window that current-
ly owns the input focus.
The system sends WM_CHAR messages by posting them to the mes-
sage queue owned by the window with the focus (in contrast to high-
priority messages sent by directly calling the window procedure). The
Presentation Manager, however, does not post a WM_CHAR message
until tha window procedure has finished processing the previous WM_CHALR
777css¢gc. (The system knows that the procedure has completed process-
ing a message when the window thread calls the WinGetMsg function
to obtain another message.) The system can post only one WM_CHAR
message at a time because the processing of a given message may
cfe¢7igc ffec /oct4s zt7€.7idoco at any time (for example, a window procedure
could call WinsetFocus or WinsetActivewindow to explicitly change
the focus or the active window). If the Presentation Manager posted
a second keyboard message to the focus window before the first mes-
sage was processed, the second message could end up being sent to the
wrong window. Note that if no window currently owns the focus, the
WM_CIIARmessageissenttotheactivewindow(theconceptofthefocus
and active window was discussed in the section of Chapter 4 on Creating
the Scroll Bars).
Figure 6.1 describes the WM_CHAR message. As you can see from
this description, a large amount of information is encoded in the two
messageparameters,mplandmp2,thatarepassedtothewindowproce-
dure. Fortunately, the system provides a macro, CHARMSG, that
simplifies extracting specific values from these parameters. This macro
works in conjunction with a specially defined structure ®oth the macro
and the associated structure are defined in the PMWIN.H header file). The
definition of the macro is somewhat complex; however, its use is simple.
The fouowing table hsts the values you can extract with this macro:

Macro Format Value Extracted


from Parameters
CHARMSG (&msg)->scancode Hardware scan code
CHARMSG (&msg)->chr Character code
AddingaKeyboardlnterface 229 .

CHARMSG (&msg)->vkey Virtual-key code


CIIARMSG (&msg)->cRepeat Repeat count
CHARMSG (&msg)->fs Keyboard control flags

Note that msg is the name of the second parameter (the message iden-
tifier) passed to the window procedure in the example program. If your
program uses a different name for this parameter, substitute this name
in the preceding expressions; otherwise, the expressions should be ex-
actly as listed.

WM CHAR
Purpose..
Sent by the system to the focus window (or active window, if
there is no focus window) to notify it of a keyboard event
(that is, a key pressed or released).

Parameters..
REJ- mpl
low-order 16 bits: Keyboard control flags; the individual
flags can be extracted using the
following identifiers:

Identifier Meaning If Flag Is Set


KC CHAR Character code is valid
KC SCANCODE Scan code is valid
KC VIRTUALKEY Virtual-key code is valid
KC KEYUP The key was released
(otherwise, the key was
pressed)
KC PREVDOVVN The key was previously
down (otherwise, it
was previously up)

• Figure 6.1..
The WM_CHAR Presentation Manager message
• 230 Programmer's Guide to the os/2 Presentation Manager

KC DEADKEY The key is a dead key


(a keystroke that
should not advance the
cursor, such as an
umlaut)
KC COMPOSITE Key code was obtained
by combining current
key with previous
dead key
KC INVALIDCOMP Current key does not
form a valid
combination with
previous dead key
KC LONEKEY The key was pressed
and released without
other keys being
pressed between the
time the key went
down and up
KC SHIFT The Shift key was
down when the key
was pressed or released
KC ALT The Alt key was down
when the key was
pressed or released
KC CTRL The Ctrl key was down
when the key was
pressed or released

next 8 bits: Repeat count.


high-order 8 bits: Hardware scan code.
REA- mp2
low-order 16 bits: Character code (if KC_CHAR flag is
set); typically an ASCII code.
high-order 1 6 bits: Virtual-key code (if KC_VIRTUALKEY
flag is set); see Table 6.1 for a list of
some of these codes.

Return Value ..
Return TRUE if the message was processed, or FALSE if the
message was ignored.

• Figure 6.1..
The WM_CHAR Presentation Manager message (continued)
AddingaKeyboardlnterface 231 .

The Scan Code


The scan code is a number identifying the specific key on the key-
board. The meaning of a given scan code depends upon the particular
keyboard hardware that is installed; therefore, you should not use these
codes if your program is to remain device-independent. You can find
the meanings of the scan codes for a given machine in the appropriate
hardware technical reference manual. (Many MS-DOS applications,
which are typically targeted to a narrow range of machine models, rely
upon the hardware scan codes.)

The Character Code


For all keystrokes that represent characters-letters, numbers, or
symbols-the Presentation Manager translates the scan code into a
hardware-independent character code. This code is typically the stand-
ard ASCII value of the key, although the system may be con figured to
use EBCDIC values or extended codes for foreign keyboards. The
Presentation Manager derives this code based upon the following data:

• The hardware scan code indicating the specific key pressed or


released
• The current state of the shift keys-Alt, Ctrl, and shift
• The currently installed translation table, which maps scan-
c,ode/shift-state combinations into the appropriate character
codes for the specific country and computing environment

The Virtual-Key Code


The Presentation Manager introduces a new class of keystroke iden-
tifiers known as z7z.7'£t/#J codes. A virtual code is a hardware-independent
value used to identify keys that do not have character values, such as
function keys, arrow keys, the Ins key, and so on. (Note that certain keys
may have Z7offr a character code and a virtual code, such as the Enter
key.) Table 6.1 lists the virtual code identifiers provided by the system
header files. Unlike scan codes, the virtual code for a key with a given
• 232 Programmer's Guide to the os/2PresentationManager

label (such as ``F1" or ``Home'') does not depend upon the specific key-
board hardware. Therefore, a program that uses these keys will remain
device-independent. Note, however, that the codes in Table 6.1 marked
with an * are not generated by all keyboards; if you use these codes in
your application, you should provide alternative keystrokes.
In the same manner as the character codes, the Presentation Manager
derives the virtual code from the hardware scan code using the current-
ly installed translation table. In general, however, the shift state does
not affect the virtual code.

The Repeat Count


Typically, the keyboard hardware automaticauy sends a series of
repeated signals when you hold a key down longer than a certain
threshold period. As mentioned, the Presentation Manager posts
WM_CIIAR messages one at a time; an application, however, may not be
fast enough to process the keystrokes at the same rate they are generated.
Therefore,insteadofpostingaurepeatedkeystrokesinthefocuswindow's
queue, the Presentation Manager posts a single message that contains a
count of the total number of repetitions that ocourred since the last key
message was extracted from the queue. This procedure, known as co¢Zcsc-
I.7tg repeated keystrokes, helps prevent an application from receiving key-
board messages faster than it can process them.
If your program needs to handle every keystroke, it can execute its
processing routine the number of times indicated by the repeat count
(for example, by placing this routine within a loop and using the repeat
value as the loop counter). The example program, however, simply ig-
nores the repeat count, since it may be unable to process keys rapidly
enough to handle all repeated keystrokes (especially if the keyboard
repeat rate is set at a high value). For example, if you scroll the window
toward the end of the file by keeping the J key depressed, the program
must scroll the entire screen contents with each keystroke processed,
whichisatime-cousumingprocedure.Iftheprogramattemptedtoprocess
every repeated keystroke, keystrokes would most likely accumulate in the
systemqueue;asaconsequence,whenyoureleasethekey,manymessages
would be left in the queue and the window would continue to scrou long
after the J key was released. Such distressing overscrouing can be
ehminated by silnply disregarding the repeat count.
AddingaKeyboardlnterface 233 .

• Tlable 6.1.. The virtual-K

Identifier Value (hex) Notes


*
VK BREAK Ox04

VK BACKSPACE 0x05 Backspace


VK TAB 0x06 Tab
VK BACKTAB 0x07 Shift-Tab
VK NEVVLINE 0xO8 Enter
VK SHIFT 0xO9 Shift
VK CTRL 0xOA Ctrl
VK ALT 0xOB Alt (down only)
*
VK ALTGRAF 0xOC
*
VK PAUSE 0xOD
VK CAPSLOCK 0xOE Caps Lock
VK ESC 0xOF Esc
VK SPACE 0xl0 Spacebar
VK PAGEUP 0xll P8Up
VK PAGEDOIN Oxl2 P8Dn
VK END 0xl3 End
VK HOME 0xl4 Home
VK LEFT 0xl5 Left-arrow
VKUP 0xl6 Up-arrow
VK RIGHT 0xl7 RIght-arrow
vK rowN 0xl8 Down-arrow
VK PRINTSCRN 0xl9 Shift-Prtsc
VK INSERT 0xlA Ins
VK DELETE 0xlB Del
VK SCRLLCX=K 0xlc Scroll Lock
VK NUMLOCK 0xlD Num Lock
VK ENTER 0xlE * (not the normal
Enter key)
• 234 Programmer's Guide to the os/2 Presentation Manager

• Table 6.1.. The Virtual-Key Codes (continued)

Identifier Value (hex) Notes


VK_SYSRQ OxlF * Sys Req

VKFI 0x20 FI
VKF2 0x21 F2
VKF3 0x22 F3
VKF4 0x23 F4
VKF5 0x24 F5
VKF6 0x25 F6
VKF7 0x26 F7
VKF8 0x27 F8
VKF9 0x28 F9
VK F10 0x29 F10
*F11
VK Fll 0x2A
VK F12 0x2B *F12

0x2C *F13
VK F13
VK F14 0x2D *F14

VK F15 0x2E *F15

0x2F *F16
VK F16
0x30 *F17
VK F17
*F18
VK F18 0x31
0x32 *F19
VK F19
VK F20 0x33 *F20
*F21
VK F21 0x34
VK F22 0x35 *F22

VK F23 0x36 *F23


*F24
VK F24 0x37
VK MENU VK ALT Alt

* Marks codes that are not generated by all keyboards


AddingaKeyboardlnterface 235 .

The Keyboard Control Flags


Each keyboard message also includes a 16-bit value containing key-
board control flags. The individual bits of this word serve as flags indicat-
ing the state of the keyboard at the tine the key was pressed or released.
You can access the desired bit by using the appropriate constant as a bit
mask; constants are provided in the PMWIN.H include file, and are hated
in Figure 6.1. The binary value of each of these constants consists of all
zeros, with a single 1 in the position of the appropriate bit of the flag word;
you can therefore use the constant in conjunction with the & operator to
test whether the given flag is set. For example, the sixth bit in the control
flag word is set when the key has been released and is zero when the key
has been pressed; accordingly, the constant KC_KEYUP has the value
Ox0040, and can be used as fonows:

if (CIIARMSG (&msg)->fs & KC KEYUP)


/* then key was released,. therefore ignore message*/
else
/* then key was pressed,. therefore process message*/

Figure 6.2 lists the WM_CIIAR routine within the client window pro-
cedure (Wndproc) of the example program, which uses the keyboard
flags to perform the initial processing of all keyboard messages. This
routine first tests the KC_KEYUP bit of the control flags to determine
whether the key was pressed or released. If the key was released, the
window procedure immediately returns FALSE, which indicates to the
system that the key message was ignored (returning TRUE notifies the
system that the key was processed).
Next, the program tests the KC_CHAR bit of the control flags. If this
flag is set, then the keyboard message contains a valid character code
and control passes to the function Character, which processes all char-
acter keys and is described in the next section. If the message does not
contain a valid character code, then the routine goes on to test the
KC_VIRTUALKEY flag. If this flag is set, then the message has a valid
virtual code, and the program calls the VirtKey function to process
the virtual key; this function is described later in the chapter. Finally, if
neither flag is set, the window procedure returns immediately; theoreti-
cally, this case should never occur.
• 236 Programmer's Guide to the os/2 Presentation Manager

case WM CHAR: /* Message sent when keyboard key is received. */

/*** Don't process a key-released message. *************************/


if (CHARMSG (&msg)->fs & KC KEYUP)
return FALSE;

/*** Process character key. ****************************************/


else if (CHARMSG (&msg)->fs & KC CHAR)
return Character (hwnd, msgT mpl, mp2) ;

/*** Process virtual key. ******************************************/


else if (CHARMSG (&msg)->fs & KC VIRTUALKEY)
return VirtKey (hwnd, msg, ripl, mp2) ;

/*** Don't process invalid key. ************************************/


else /* Invalid key: neither virtual nor character. */
return FALSE;

• Figure 6.2..
The initial processing of the WM_CHAR message

• THE CHARACTER KEYS


All WM_CHAR messages with valid character codes are pro-
cessed by the function Character in the example program. This function
contains separate routines for each of the following keys:

• Backspacekey
• Tabkey
• Enterkey
• All remaining character keys

Processing any of these keys results in modifying the contents of the


file buffer-adding, deleting, or changing characters. In the previous
version of the example program, all file lines were stored in separately
allocated memory blocks within the heap. As illustrated in Figure 3.9,
the address of each line within the heap is stored in line-number order
within the array LineTable, permitting rapid random access to any file
line. The present version of the program stores all lines within the heap
except the line that is currently being modified. Whi:le aL Tine is being
modified it is temporarily stored in a local array, LineBuffer; the size of
AddingaKeyboardlnterface 237 .

this buffer (LINEBUFSIZ, which currently equals 255 but could easily
be modified) represents the greatest line length that can be managed by
the program. The new overall data structure is illustrated in Figure 6.3.
Lines are not modified directly within the heap, because modifica-
tion usually results in a change in the line length, and the memory
blocks within the heap are the exact sizes of the lines they contain.
When you have completed altering a given line, the characters in that
line are copied into a newly allocated block within the heap, which has
a size that matches the new length of the line. File lines are modified
through the following sequence of steps:

1. When the program begins, the cursor is placed in file line o and
the data for this line is contained in LineBuffer. Accordingly,
LineTable [0] holds the address of LineBuffer rather than that of
a block within the heap.
2. Any character keys you enter cause the modification of the con-
tents of LineBuffer.
3. You can freely move the cursor throughout the file. If, however,
you enter a character key when the cursor is on a new line, then
the program executes a sequence of steps to store line 0 back
into the heap and place the contents of the new line into Line-
Buffer. This sequence of steps is repeated each time you enter a
character key into a 71cw line.

The number of the line that was most recently modified is stored in
the variable LastcursorLine. Accordingly, the function Character first
compares LastcursorLine with CursorLine, the line currently contain-
ing the cursor. If these values are unequal, then the user has moved the
cursor to a new line and is in the process of modifying this line by enter-
ing a character key. Therefore, the program performs the sequence of
steps necessary to store the former line back into the heap and to copy
the new line into LineBuffer. The code that makes this test and per-
forms these steps is as follows:

if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ,.
GetTempBuf (CursorLine) ,.
• 238 Programmer's Guide to the os/2 Presentation Manager

• Figure 6.3..
The data structure used to store and modify the file lines
AddingaKeyboardlnterface 239 .

LastcursorLine = CursorLine,.
)

The function ReleaseTempBuf, located in the buffer-management


module of the example program, is listed in Figure 6.4. This function is
passed the number of the line that was most recently modified (Last-
CursorLine), and performs the following steps:

1. It allocates a block within the heap just large enough to hold the
modified line currently contained in LineBuffer.

void ReleaseTempBuf
(int Line) /* Number of line held in 'LineBuffer' .
/*
This function:
o Allocates a new block of memory just large enough to hold the string in
the 'LineBuffer'
o Copies the string into the new block
o Adjusts the address in 'LineTable'
*/
(
NPCH Heapoffset; /* Offset of block within heap. */

/*** Allocate a block to hold current contents of 'LineBuffer' . **************/


Heapoffset = WinAllocMem
(HHeap,
LineTable [Line] .LineLength) ;
if (Heapof fset == NULL)
(
sprintf (Message,"out of heap memory; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

/*** Copy characters from 'LineBuffer' into new block in heap. ***************/
movedata /* Intersegment block copy. */
(Lineselector, /* Source: selector of line buffer. */
Lineoffset, /* Source: offset of line buffer. */
Heapselector, /* Target: selector of heap. */
(unsigned)Heapoffset, /* Target: offset of new block. */
LineTable [Line].LineLength) ; /* Bytes to copy. */

/*** Adjust address in 'LineTable' to point to new block. ********************/


LineTable [Line].LineAddress = MAKEP (Heapselector, Heapoffset) ;

} /* end ReleaseTempBuf */

• Figure 6.4..
The function ReleaseTempBul of the example program
• 240 Programmer's Guide to the os/2 PresentationManager

2. It copies the contents of modified line from LineBuffer into the


new block in the heap.
3. It adjusts the appropriate entry in LineTable to point to the new
heap block instead of to LineBuffer.

Note that the data are copied by calling the C function movedata, which
generates an efficient intersegment block-copy operation.
The function GetTempBuf (listed in Figure 6.5) is called next; this
function is also in the buffer-management module. GetTempBuf is

void GetTempBuf /* Places specified line into 'LineBuffer' .


(int Line) /* Number of line.
/*
This function:
o Copies the string in the specified line into 'LineBuffer'
o Frees the block formerly holding the string
o Adjusts the address in 'LineTable'
*/
(
/*** Copy string into 'LineBuffer'. ******************************************/
movedata /* Intersegment block copy.*/
(SELECTOROF (LineTable[Line].LineAddress) , /* Source segment. */
OFFSETOF (LineTable[Line].LineAddress) /* Source offset. */
Lineselector , /* Target segment. */
Lineo f f set , /* Target offset. */
LineTable [Line] .LineLength) ; /* p;rytes to ccfpry. */
/*** Release block formerly holding line. ************************************/
if (WinFreeMem
(HHeap, /* Handle of heap from 'WincreateHeap' .
(BYTE NEAR *)OFFSETOF (LineTable [Line].LineAddress), /* Offset.
LineTable [Line].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message,"managing heap; line %d", LINE );
ErrorQuit (Message) ;
)

/*** Place new address into 'LineTable'. *************************************/


LineTable [Line] .LineAddress = MAKEP (Lineselector,Lineoffset) ;

} /* end GetTempBuf */

• Figure 6.5..
The function GeITe"pBuf of the example program
AddingaKeyboardlnterface 241 .

passed the number of the new line that is about to be modified (Cursor-
Line), and performs the following steps:

1. It copies the line that is about to be modified from the heap into
LineBuffer.
2. It-releases the block formerly used to hold this line within the
heap.
3. It adjusts the appropriate entry in LineTable to point to Line-
Buffer rather than to the heap block.

The modifications to the file data structure made by the calls to


ReleaseTempBuf and GetTempBuf are illustrated in Figure 6.6. Once
the former line has been safely stored away in the heap, and the current
line is ready to modify in LineBuffer, the program updates Lastcursor-
Line to contain the current cursor line.
At this point, whether or not the file buffer needed to be adjusted, the
function Character branches to the appropriate routine to process the spe-
cific character key. Each of these routines is discussed in the remainder of
this section, in the order of increasing complexity.

Normal Character Keys


This section discusses the processing of all character keys that do
not have special control significance in the example program (that is, all
keystrokes that generate a valid character code except Backspace, Tab,
and Enter). These keys are inserted directly into the data buffer; the
routine that processes them is listed in Figure 6.7. This routine
demonstrates the four basic steps required to perform an editing opera-
tion on the file. Several of the other routines in the program follow these
same general procedures, which can be summarized as follows:

1. Call the appropriate function in the buffer-management module


to effect the internal change to the file data structure.
2. Signal the user if the maximum line length or maximum heap
size has been reached and the editing function cannot be
performed.
• 242 Programmer's Guide to the os/2 Presentation Manager

• Figure 6.6..
The changes made by ReleaseTe:mpBuf and GeITe"pBuf to the file data structure
AddingaKeyboardlnterface 243 .

3. Invalidate the region of the window that must be updated to


reflect the change just made to the file buffer, and call Win-
Updatewindow to expedite the repainting of the window.
4. Update the position of the cursor by sending the appropriate
scrolling message back to the window procedure.

The routine first inserts the character into the file buffer by calling the
function Insertchar (located in the buffer-management module and

/*** Process all remaining character keys. ***********************************/

/*** Insert key into file buffer. ********************************************/


if (!Insertchar
( CursorLine ,
CIIARMSG ( &msg) ->chr ,
Cursorcol ,
Insert) )
(
/*** Beep if insertion failed (max buffer length exceeded) . *************/
WinAlarm (HWND DESKTOP, WA ERROR) ;
return TRUE;
)

/*** Invalidate window from cursor position to end of line (or window) . ******/
Rect.xLeft = (Cursorcol -Firstcol) * xchar;
Rect.xRight = min ((GetLineLength (CursorLine) -Firstcol) * xchar, xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
WinlnvalidateRect /* Invalidate section to be modified. */
£R:::; ,: ::::::g:: ::i::ta::::°¥; invalid region. :,
FALSE) ; /* Don't include descendants w/ WS_CLIPCHILDREN*/

Winupdatewindow (hwnd) ; /* Force updating of client window. */

/*** Move the cursor right one column. ***************************************/


WinsendMsg /* Send right-key message to self .
(hwnd, /* Client window handle.
WM CHAR, /* Character message.
MPFROM2SHORT (KC VIRTUALKEY,1) , /* mpl.
MPFROM2SHORT (O,-VK RIGHT) ) ; /* mp2.

return TRUE;

• Figure 6.7..
The routine for processing normal character keys
• 244 Programmer's Guide to the os/2PresentationManager

listed in Figure 6.8). Insertchar is passed the character to insert


(CHARMSG(&MSG)->chr), the row and column position of the inser-
tion point within the file (CursorLine and Cursorcol), and a flag con-
taining the current insert mode (Insert). Note that the program is in the
insert mode when the global variable Insert is set to 1, and it is in
the overwrite mode when this variable is set to 0. Insert is initialized to
1, placing the program initially in the insert mode, and it is toggled in
response to the Ins key (the processing of this key is explained in the
section on the virtual keys).
Insertchar returns TRUE if the character was successfully inserted,
and FALSE if inserting the character would cause the maximum line
length to be exceeded. The character is written into LineBuffer (which
contains the file line currently being modified) at the specified column
position, which corresponds to the current position of the cursor in the
window. If the insert mode is active, any existing characters at the inser-
tion point or to the right of this point (that is, at larger offsets) are
moved one byte toward the end of the buffer. If the overwrite mode is
active, the new character is simply written over any existing character.
If the specified insertion point is beyond the current end of the line, the
function pads the buffer with space characters between the end of
the line and the new character. In all cases, the line is terminated with a
newline character ('\n') followed by a null ('\0'), and the line length in
LineTable is adjusted to the new length. Note that buffer characters are

int Insertchar /* Inserts character into 'LineBuffer'


(SHORT Line, /* Number of line for insertion.
USHORT Character, /* Character to insert.
SHORT Column, /* Column position of character.
int Insert) /* Flag indicating overwrite mode.
(
unsigned char LineLength;
/*** Obtain the length of the line. ******************************************/
LineLength = LineTable [Line] .LineLength;

/*** If line would exceed maximum line length, return without inserting. *****/
if (Column > LINEBUFSIZ - 3 I I LineLength >= LINEBUFSIZ && Insert)
return FALSE;

/*** If column is at end of line (common case) , use fast routine to insert. **/
else if (Column == LineLength - 2)

• Figure 6.8..
The function lr\sertchar of the exanple program
AddingaKeyboardlnterface 245 .

(
/*** Copy '\n' and '\0' to new position. ********************************/
LineBuffer [Column + 2] = IiineBuffer [Column + 1] ;
IjineBuffer [Column + 1] = IjineBuffer [Column] ;

/*** Write the character. ***********************************************/


LineBuffer [Column] = (char)Character;

/*** Adjust line length. ************************************************/


++LineTable [Line].LineLength;
return TRUE;
)

/*" If column is BEYOND end of line, must pad line with spaces. *************/
else if (Column > LineLength -2)
(
/*** Copy '\n' and '\0' to new position. ********************************/
LineBuffer [Column + 2] = LineBuffer [LineLength -1] ;
IjineBuffer [Column + 1] = LineBuffer [LineLength -2];

/*** Fill line with spaces. *********************************************/


memse!:::::u:f::n:L:::::e:9::;-2' ;: ::=;::::a::p::i:i:::?. :;

/*** Write characcer. ******.*:**?*_:****:*********************************/


LineBuffer [Column] = (char)Character;

/*** Adjust line length. ************************************************/


LineTable [Line].LineLength = (unsigned char)Column + 3;
return TRUE ;
)
/*** Otherwise, must insert character in middle of line. *********************/
else
(
/*** If insert mode is active, move all characters right of insertion
point one space to the right. **************************************/
if (Insert)
(
memmove /* Move block.
(LineBuffer + Column + 1, /* Target.
LineBuffer + Column, /* Source.
LineLength -Column) ; /* Number of bytes.

/*** Adjust line length. *******************************************/


++LineTable [Line].LineLength;
)
/*** Write character. ***************************************************/
LineBuffer [Column] = (char)Character;
return TRUE;
)

) /* end Insertchar */

• Figure 6.8..
The function lr\sertchar of the example progran (continued)
• 246 Programmer'sGuideto the os/2Presentation
Manager

WinAlarm
Puxpose..
Sounds the computer speaker.

Prototype..
B00L APIENTRY WinAlarm
(HWND hiirndDesktop, Desktop window handle
(INND DESKTOP).
ULONG rgfType) ,. The type of alarm; can be one of the
fonowing values:
WA WARNING
WA-NOTE
WA-ERROR

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
The alarms generated by this function can be enabled and dis-
abled, and also their frequency or duration modified, through
the function Winsetsysvalue. The constants passed to Win-
Setsysvalue to perform these adjustments are as fonows:

Value Identifier Purpose


SV ALARM Disable or enable the alarm
generated by WinAlarm.
SV_ALARMFREQ Set the alarm frequency.
SV ALARMDURATION Set the alarm duration.

Related Functions ..
Winsetsysvalue

• Figure 6.9..
The WLnALla;rm Presentation Manager function
AddingaKeyboardlnterface 247 .

moved via a fast intrasegment block-copy operation generated by the C


function memmove, rather than character by character in a loop. AI-
though the source and destination areas for this copy operation over-
lap, memmove is designed to correctly handle overlapping areas.
If the call to Insertchar returns an error code (FALSE), then the char-
acter routine calls the Presentation Manager function WinAlarm (Fig-
ure 6.9), which creates a warning sound that notifies the user that the
line has reached its maximum length. The routine then stops processing
by issuing a return statement.
If the call to Insertchar is successful, the routine calls Winlnvalidate-
Rect to cause repainting of the section of the window that displays the
recently altered data. Specifically, the invalid rectangle is assigned
the coordinates of the portion of the current line (CursorLine) extend-
ingfromtheinsertedcharactertotheendoftheline(ortotheendofthe
window if the line extends beyond the right window border). The
dimensions of the invalid rectangle are assigned to the four fields of the
RECTL structure Rect (Rect.xLeft, Rect.xRight, Rect.yBottom, and
Rect.yTop). If you study the expressions that calculate these values, you
will notice that Rect.xRight is assigned the number of the pixel immedi-
ately fo ffec r!.gfef of the area that needs to be invalidated, and that
Rect.yTop is given the number of the pixel immediately ¢Z7oz7c the rec-
tangle containing the altered characters. These expressions thus seem to
indicate a rectangle that is one pixel wider and higher than required.
Under the Presentation Manager, however, rectangles are specified by
giving the coordinates of the pixel at the lower left corner, and the coor-
dinates of the first pixel above and to the right of the pixel at the upper
right corner (rather than the coordinates of the upper right pixel itself).
The routine then forces immediate repainting of the window by call-
ing Winupdatewindow. (Note that if this function were not caned, a
series of rapidly repeated characters generated by holding down a key
would cause the oursor to move, but the new characters would not appear
on the screen until the key was released. The WM_CHAR message nor-
mally has a low priority; it is not posted to the window message queue
until all prior messages in the queue have been processed.)
Finally, the character routine moves the cursor one position to the
right by calling WinsendMsg to send a recursive WM_CHAR message
for a i key. When calling this function, the program assigns the follow-
ing values to the message parameters that will be passed to the window
• 248 Programmer's Guide to the os/2Presentation
Manager

procedure:

Field Value Assigned

Hardware scan code 0


Character code 0
Virtual-key code VK RIGHT
Repeat count 1

Keyboard control flags KC VIRTUALKEY

Because the KC_VIRTUALKEY bit of the flag word is set (and the
KC_CHAR bit is off), the message is processed by the VirtKey function;
the routine that processes the arrow keys was described in Chapter 5.
Note that this routine provides another example of sending recursive
messages to avoid duplicating code. After control returns from Win-
SendMsg,thecharacterroutinereturnsTRUEtoinformthesystemthat
the key was processed.

The Tab Key


The program does not insert tab characters directly into the file
buffer. Rather, it replaces this character with the number of space char-
acters required to move the cursor to the next tab stop. The Tab-key
routine is listed in Figure 6.10; this routine first calculates the number of

/*** Process a tab key by sending equivalent number of space characters. *****/
if (CHARMSG(&msg)->chr == '\t')
(
Col = 5 -Cursorcol % 5;
while (col--)
WinsendMsg /* Send space character message to self .
( hwnd ' /* Client window handle.
WM CHAR, /* Character message.

return TRU#EE8¥2!EgE: (fcT:g?F; 1, , ,: S3:::a:::r::f;r


) /* end '\t' */

• Figure 6.10..
The Tab~key routine
AddingaKeyboardlnterface 249 .

spaces between the current cursor position and the next tab stop (the
column numbers of the tab stops are multiples of 5). It then inserts
the calculated number of space characters into the file. Each blank is in-
serted by sending a WM_CIIAR message back to the window proce-
dure, specifying the KC_CIIAR code and the space character.

The Enter Key


When you press the Enter key, the program inserts a new line into
the file (provided that the insert mode is active; if the program is in
overwrite mode, the cursor simply moves down one line and over to
the first column). The routine for processing this key (listed in Figure
6.11) follows the same four basic steps outlined in the section on Nor-
mal Character Keys; for inserting a new line, however, these steps are
more complex.

/*** Process En+er key. **"***********"*************************************/


if (CHARMSG(&msg)->chr == '\r')
(

/*** If in insert mode, insert a new line into buffer. ******************/


if (Insert)
(
/*** Insert the line into file buffer. *****************************/
InsertLine (CursorLine, Cursorcol) ;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (O,LastLine -ywin / ycharTot + 1) ;

WinsendMsg /* Adjust scroll bar range.


(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable only if scroll possible.


(HVscroll, /* Recipient handle: vertical scroll bar.
TopLineMax ? 1 : 0); /* Enable only if max. != 0.

/*** Invalidate 'CursorLine' and all lines below. ******************/


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
Winlnva i idateRect
( hwnd ,
&Rect ,
FALSE) ;

• Figure 6.1.1..
The Enter-key routine
• 250 Programmer's Guide to the os/2PresentationManager

/*** Force update of client window. ********************************/


Winupdatewindow (hwnd) ;

} /* end insert mode */


/*** Move cursor
_, __ -_ __ 1,,
down one line. *****************************************/
WinsendMsg /* Move cursor down.
(hwnd, /* Client window handle.
WM CHAR, /* Character received message.
MPFROM2SHORT (KC_VIRTUALKEY,1) ,
MPFROM2SHORT (0, VK DOWN)) ;

/*** Adjust 'LastcursorLine' if in insert mode. *************************/


if (Insert)
LastcursorLine = CursorLine;
/*** Move cursor to beginning of line. **********************************/
WinsendMsg /* Send Home key message to self. */
(hwnd, /* Client window handle.
WM CHAR, /* Character received message

¥:EE8#:§EBE: (5:-¥±R=8#rf¥J [j J /: ¥:::u=:yk:gae.


return TRUE;

) /* end '\r' */

• Figure 611..
The Enter-key routine (continued)

First, if the insert mode is active, the routine calls the function Insert-
Line, which is contained in the buffer-management module and is
listed in Figure 6.12. This function is passed the numbers of the line and
column containing the cursor (CursorLine and Cursorcol), and inserts
a new line into the file buffer immediately before the cursor position.
InsertLine copies all characters contained in LineBuffer that are Z7c/ore
the cursor position into a newly allocated block within the heap. It then
moves the remaining characters in LineBuffer to the beginning of the
buffer. Finally, it inserts a new entry into LineTable, immediately before
the CursorLine entry, which contains the address of the newly allocated
heap block. These steps are illustrated in Figure 6.13. Note that the pro-
gram can call memmove to move the elements of LineTable using a
single block-copy operation (rather than adjusting the array element by
element), since this C library function properly handles overlapping
source and target addresses.
Rather than returning the error status to the calling program, Insert-
Line handles errors internally. If the maximum number of lines (MAX-
LINES) is exceeded, or if the storage capacity of the heap is reached,
InsertLine directly terminates the program by calling ErrorQuit. In the
AddingaKeyboardlnterface 251 .

void InsertLine (SHORT Line, SHORT Column)


/*
Inserts a new line into the file buffer, immediately before character
given by 'Column' , within the line given by 'Line' .
*/
(
NPCH Heapoffset; /* Holds 16-bit heap offset. */
PCH Heappointer; /* Holds far pointer to heap base. */
/*** Fatal error if maximum lines reached. ***********************************/
if (++LastLine >= MAXLINES)
(
sprintf (Message,"maximum lines reached; line %d", LINE_) ;
ErrorQuit (Message) ;
)

/*** Adjust 'Column' to maximum position in line. ****************************/


if (Column > LineTable [Line].LineLength -2)
Column = LineTable [Line].LineLength -2;

/*** Allocate a block for characters in line before 'Column' . ****************/


Heapof fset = WinAllocMem
(HHeap,
Column + 2) ;
if (Heapof fset == NULL)
(
sprintf (Message,"out of heap memory; line %d", _LINE );
ErrorQuit (Message) ;
)

/*** Copy characters before 'Column' into new block. *************************/


movedata /* Intersegment block copy. */
(Lineselector, /* Source: selector of 'LineBuffer */
Lineof fset , /* Source: offset of 'LineBuffer'. */
Heapselector , /* Target: selector of heap. */
(unsigned)Heapoffset /* Target: offset of new block. */
Column) ; /* Number of characters to copy. */

/*** Construct a far pointer to new block in heap. ***************************/


Heappointer = MAKEP (Heapselector,Heapoffset) ;

/*** Write newline and null to end of new line in heap. **********************/
*(Heappointer + Column) = '\n';
*(Heappointer + Column + 1) = '\0' ;

/*** Move character number 'Column' and all following characters to beginning
o£ 'L±neBuffer' . ********************************************************/
memmove /* Intrasegment block copy. */
(LineBuffer, /* Target address. */
LineBuffer + Column, /* Source address. */
LineTable [Line].LineLength -Column) ; /* Bytes to move. */

/*** Adjust line length. *****************************************************/


LineTable [Line].LineLength -= (unsigned char)Column;

• Figure 6.12:
The function luseriLine of the example program
• 252 Programmer's Guide to the os/2PresentationManager

/*** Move all members of 'LineTable' one position toward end of table. *******/
memmove
(&LineTable [Line + 1], /* Target.
&LineTable [Line] , /* Source.
(LastLine -Line) * sizeof (LineTable [0])) ; /* Bytes to move.
/*** Assign address of new heap block to 'LineTable' . ************************/
LineTable [Line].LineAddress = Heappointer;
LineTable [Line] .LineLength = (unsigned char) (Column + 2) ;

} /* end InsertLine */

• Figure 6.12..
The function lnsertLir\e of the example program (continued)

current version of the example program, running out of memory is


treated as a fatal error.
Because the call to InsertLine changes the overall length of the file
(that is, LastLine is incremented), the Enter-key routine must sub-
sequently adjust the range of the vertical scroll bar. The routine per-
forms this task by adjusting TopLineMax and by calling WinsendMsg
and WinEnablewindow, in the same manner as the Size function (see
the description of Size in Chapter 4 for an explanation of these steps).
Next, the routine calls WinlnvalidateRect to invalidate the line con-
taining the cursor and all lines displayed below it within the window,
followed by the usual call to Winupdatewindow to force immediate
repainting.
All of the steps described so far are performed only if the program is
in the insert mode. Next, regardless of the mode, the program moves
the cursor down one line and to the first column by sending recursive
down-arrow and Home-key messages back to the client window proce-
dure (this is the same technique that the normal character routine,
described earlier, used to move the cursor). Note that if the program is
in insert mode (and therefore a new line was inserted), LastcursorLine
must be updated to the value in CursorLine, since CursorLine was in-
cremented yet the cursor is still within the line stored in LineBuffer.

The Backspace Key


The effect of the Backspace key depends upon whether the cursor
is in the first column (column 0) and whether the program is in the in-
sert mode. The routine that processes this key is listed in Figure 6.14.
AddingaKeyboardlnterface 253 .

CursorLine |
I

LineTable II

BEFOF3E CALL NG
lnsertLine

'
This line is adoutto bedivided\n\O I

LineBuffer A

cursorIcursorLine +1

Presentation Manager Heap

------
CursorLine i
I I

LineTableNG 1111

AFTEPI CALLllnsertLine
IIIIIm

1
out to be divided\n\O I

A LineBufferCursorwillbe
I This line is ab\n\O I

A moved here
cursor

Presentation Manager Heap

• Figure 6.13:
Inserting a new line with the lr\seithine function
• 254 Programmer's Guide to the os/2Presentation
Manager

/*** Process a Backspace key. ************************************************/

if (CHARMSG(&msg)->chr == '\b')
(
/*** If cursor is at column 0, must join line to previous line. *********/
if (Cursorcol == 0)
(
/*** NO previous line if cursor is in first line. ******************/
if (CursorLine == 0)
return TRUE;

/*** Move cursor one line up. **************************************/


w`nse#::ii::E8:: (5:_¥±=i:?:;:;:¥::::;:|i:;::;::;:;:;f :;

/*** Move
- cursor to end of line. ***********************„**********/
winse?:::g, /: ::::nEn:i::::ag:n::e:elf.
WM CHAR, /* Character received message.

#:EEg#2§EBE: tg:_¥ER=¥3Tf¥y, 1, , ,: £n¥±::::: key


/*** If in overwrite mode, return without joining lines. ***********/
if (!Insert)
return TRUE;

/*** Join line to previous line. ***********************************/


if (!ToinLine (CursorLine + 1))
(
/*** Sound alarm if join fails (max line length exceeded) . ****/
WinAlarm (HWND DESKTOP, WA ERROR) ;
return TRUE;
)

/*** Adjust 'LastcursorLine'. **************************************/


LastcursorLine = CursorLine;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;

WinsendMsg /* Send message to vertical scroll bar.


(HVscroll, /* Recipient handle.
fBfE3E!!:33!L?3:;Line, o) , /* Se;*ps:::i::n: range.
MPFROM2SHORT (0, TopLineMax) ) ;. /* Range.

WinEnablewindow /* Enable only scroll possible.


(HVscroll, /* Recipient handle.
TopLineMax ? 1 : 0); /* Enable only if max. != 0.

/*** Invalidate joined line and all lines below. *******************/

• Figure 6.14..
The Backspace-key routine
AddingaKeyboardlnterface 255 .

Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
wLn|nli:§§;:eRej::::i::;ii::i::i::§i:i::i:::;:::;::;;;;;iDREN;j

/*** Force window update. ******************************************/


Winupdatewindow (hwnd) ;

/*** TRUE signals that key was processed. **************************/


return TRUE;

} /* end cursor at column 0 */


/*** Remaining code is for cursor NOT at column 0. **********************/

/*** Move cursor back one space. ****************************************/


W±nse?hi:a, /: ::I:n:e::i:::Oxa::::?ge t° Self. :/
wh CHAR, /* Character received message
#:::8:2SE8:: (5:-¥:R::::fT?,1, , ,: :::::::r::y;ode.
/*** If in insert mode, delete character. *******************************/
±f ([£::::idMsg /* send Del message to self.

#W:£AR, /: :::=::t::n::¥e::::i:;ssage.
#:ER8#2§E8R: (5:-¥:R:¥£T¥¥y, i] , /: ¥::t=:; ::¥;
/*** If in overwrite mode, overwrite current character with a space. ****/
else
(
/*** Print a space character. **************************************/
WinsendMsg /* Send space character message to self . */
(hwnd, /* Client window handle. */
WM CHAR, /* Character message. */
MPFROM2SHORT (KC_CHAR,1) , /* Character key. */
MPFROM2SHORT (' I ,0)) ; /* Space character. */

/*** Restore cursor position (printing space advanced it!) . ********/


WinsendMsg /* Send left-arrow message to self. */
#W::AR, /: ::::::t::n::¥e::::i:;ssage. :/
#:i::#2SE8E= (5:-¥:R:¥£:rf¥' L' ' /: ¥:=::::r::y;ode. :/
} /* end overwrite mode */
/*** Signal system that key was processed. *******************************/
return TRUE;

) /* end '\b' */

• Figure 6.14..
The Backspace-key routine (continued)
• 256 Programmer's Guide to the os/2 PresentationManager

If the cursor is beyo7id the first column and the program is in insert
mode, the Backspace-key routine moves the cursor back one space by
sending a left-arrow message to the window procedure, and then
deletes the character at the new position by sending a Del-key message
(the Del key is processed by the VirtKey routine, discussed later in the
chapter). If the program is in the overwrite mode, then the routine
moves the cursor back one space, and writes a space character at the
new position by sending a character message; it must then send a left-
arrow message to restore the cursor position (writing the space ad-
vanced the cursor; the cursor, however, should remain at the newly
blanked position). Note that many editors do not distinguish between
insert and overwrite modes when performing a backspace operation;
however, replacing the preceding character with a space rather than
deleting it prevents shifting left all the remaining characters in line. A
design goal of the example editor is that in the overwrite mode, editing
operations should not normally alter the relative positions of characters
(exceptions are the F9 and Del keys).
If the cursor is at column 0 and the program is in insert mode, then
the routine /.oz.71s the current line with the previous line, conceptually
deleting the preceding newline character (provided, of course, that the
cursor is not in the first line of the file). Note that using the Backspace
key to join lines is one of two common options; alternatively, many
editors join lines when you press the Del key at the end of the preceding
line (and some editors use both methods).
The backspace routine joins lines by moving the cursor to the end of
the previous line and calling the function ToinLine, which is part of the
buffer-management module and is listed in Figure 6.15. JoinLine is
passed the number of the line that is contained in LineBuffer (which, at
this point, is CursorLine + 1); it first moves the characters in this line far
enough toward the end of the buffer to make room for the characters
belonging to the previous line. It then copies the characters from the
previous line into the beginning of LineBuffer. Finally, JoinLine frees
the heap memory occupied by the previous line, and deletes the cor-
responding entry from LineTable. These operations are illustrated in
Figure 6.16.
If JoinLine returns an error code (FALSE), the backspace routine
sounds the alarm by calling WinAlarm and returns. Otherwise, it per-
forms the standard tasks of adjusting the vertical scroll bar range and
invalidating the affected area of the window.
AddingaKeyboardlnterface 257 .

int ToinLine (SHORT Line)


/*
Combines the line in the file buffer given by 'Line' with the previous
line.
*/
(
/*** Return if 'Line' is the first in the file (no previous line) . ***********/
if (Line -- 0)
return FALSE;

/*** Return if combined length would exceed maximum line length. *************/
if (LineTable [Line].LineLength + LineTable [Line -1].LineLength -2 >
LINEBUFSIZ)
return FALSE;

/*** Move existing characters in 'LineBuffer' to right to make room for the
characters from previous line. ******************************************/
memmove

i±::::¥f::: + LineTable [Line -1].LineLength - 2, /: g:::::


LineTable [Line].LineLength) ; /* Number of bytes

/*** Move the characters from previous line to beginning of 'LineBuffer' . ****/
movedata
(SELECTOROF (LineTable [Line -1].LineAddress) ,
OFFSETOF (LineTable [Line -1].LineAddress) ,
Lineselector ,
Lineof fset ,
LineTable [Line -1] .LineLength -2) ;

/*** Adjust line length for added characters. ********************************/


LineTable [Line] .LineLength += LineTable [Line -1] .LineLength -2;

/*** Free block used by previous line. ***************************************/


if (WinFreeMem
(HHeap, /* Handle of heap from 'WincreateHeap'.
(BYTE NEAR *)OFFSETOF (LineTable [Line-1].LineAddress) , /* Offset.
LineTable [Line-1].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message,"managing heap; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

/*** Move all 'LineTable' members above and including 'Line' down one place. */
memmove

!!I:::::::e[i::::,_ 1' , /: B::::::tion. :/


(LastLine -Line + 1) * sizeof (LineTable [0])); /* Bytes to move.*/
/*** Adjust 'LastLine'. ******************************************************/
--LastLine ;

return TRUE;

} /* end JoinLine */

• Figure 6.15..
The function Jo3:nLine of the example program
• 258 Programmer's Guide to the os/2 Presentation Manager

• Figure 6.16..
Joining two lines with the Jo±nLine function
AddingaKeyboardlnterface 259 .

Finally, if the cursor is in column 0 and .the overwrite mode is active,


the backspace routine simply moves the cursor to the end of the pre-
vious line wz.£feo#£ joining the two lines (in keeping with the philosophy
that operations in the insert mode should not alter the relative positions
of characters).

• THEVIRTUALKEYS
When the main client window procedure, Wndproc, detects that
the WM_CHAR message contains a valid virtual code, it calls the Virt-
Key function to process the key. This function branches to the ap-
propriate routine according to the virtual code that identifies the
specific key, using the following switch statement:

switch (CIIARMSG (&msg) ->vkey)

The codes for the virtual keys are listed in Table 6.1. VirtKey contains
routines for the following subset of these keys:

Key Virtual code Routine


1 vK UP Figure 5.11
J VK DOWN Figure 5.11
+ VK LEFT Figure 5.11
i VK RIGHT Figure 5.11
Pgup VK PAGEUP Figure 5.14
PgDn VK PAGEDOWN Figure5.14
Home VK HOME Figure 5.13
End VK END Figure 5.13
F9 VK F9 Figure 6.17
Delete VK DELETE Figure 6.19
Insert VK INSERT (in Figure 6.24)

If the virtual code is not one of those listed above, VirtKey returns
the value FALSE, indicating that the message was ignored. Note that
the only routines not already discussed in Chapter 5 are those for the F9
key, the Del key, and the Ins key.
• 260 Programmer's Guide to the os/2 Presentation Manager

The F9 Key
In response to the F9 key, the program erases the entire line con-
taining the cursor. The routine that handles this key is listed in Figure
6.17. The routine first calls the function DeleteLine, which belongs to
the buffer-management module and is listed in Figure 6.18. DeleteLine
is passed the address of the line containing the cursor (CursorLine) and
performs the following three tasks:
• It calls GetTempBuf, passing it the number of the line that
/oZJozus the line to be deleted. GetTempBuf (listed in Figure 6.5
and explained earlier in the chapter) copies this following line

/*** Process F9 key: delete line containing cursor. ********************/


case VK F9:

/*** If modifying a new line, must place line in temporary buffer. */


if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)

/*** Delete line containing the cursor. ****************************/


DeleteLine (CursorLine) ;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
WinsendMsg
(HVscroll, /* Recipient handle.
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax)) ; /* Range.
WinEnablewindow
(HVscroll, /* Recipient handle. */
TopLineMax ? 1 : 0); /* Enable only if max.!= 0*/

/*** Invalidate 'CursorLine' and all lines below. ******************/


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
WinlnvalidateRect /* Invalidate section to be modified.
(hwnd, /* Handle of client window.
&Rect, /* Rectangle to be added to invalid region
FALSE) ; /* No descendants w/ WS CLIPCHILDREN.

Winupdatewindow (hwnd) ; /* Force updating of client window. */


return TRUE;

• Figure 6.17..
The F9 routine
AddingaKeyboardlnterface 261 .

void DeleteLine (SHORT Line)


/*
Deletes the specified line ('Line', which must be the line currently
containing the cursor) from the file buffer.
*/
(
/*** If line to be deleted is the last file line, merely truncate it. ********/
if (Line == LastLine)
(
LineBuffer [0] = '\n';
LineBuffer [1] = '\0';
LineTable [Line].LineLength = 2;
)
else
(
/*** Place the following line into 'LineBuffer'. ************************/
GetTempBuf (Line + i) ;

/*** Move all LineTable elements beyond deleted line down one element. **/
memmove
(&LineTable [Line] , /* Target.
&LineTable [Line + 1], /* Source.
(LastLine -Line) * sizeof (LineTable [0])) ; /* Number bytes

/*** Adjust 'LastLine'. **************************************************/


--LastLine ;
)

} /* end DeleteLine */

• Figure 6.18..
The function DeleteLine of the exanple program

into LineBuffer (writing over the deleted line) to ready it for


editing.
It deletes the entry in LineTable for the line that is being
removed by moving all entries above this entry one position
toward the beginning of the array. Again, the array manipulation
is performed using a fast block-copy operation generated by the
memmove function.
• It decrements LastLine.

If, however, the line to be deleted is the last in the file, DeleteLine simp-
ly truncates this line by writing the `\n' and `\0' characters to the first
two positions in LineBuffer.
After calling DeleteLine, the F9 routine must adjust the vertical scroll
bar range for the new file length. It performs this task in the same man-
ner as the Enter routine and the Size function. Next, it invalidates the
line containing the cursor-and all lines displayed below it-by calling
• 262 Programmer's Guide to the os/2 Presentation Manager

WinlnvalidateRect. Finally, it calls Winupdatewindow to force imme-


diate repainting of the invalid lines. Note that deleting a line causes all
lower lines to scroll up one position, while the cursor remains in its
same position; therefore, the F9 routine does not have to send a message
to reposition the cursor.

The Del Key


The routine for the Del key is listed in Figure 6.19. Since this key
causes modification of the line containing the cursor, the routine issues
a sequence of instructions that assure that this line is held in the tern-
porary modification buffer (LineBuffer). These instructions are the
same as those at the beginning of the Character routine, explained ear-
lier in the chapter.
The Del-key routine next calls the function Deletechar (Figure 6.20),
belonging to the buffer-management module. This function is passed
the row and column positions of the character currently containing the
cursor (CursorLine and Cursorcol), and it deletes this character from
LineBuffer. Note that when deleting a given character from the line,
Deletechar moves all characters beyond it one space left.
If the specified character position is beyond the end of the hne
(caused by pressing the Del key when the cursor is positioned past the
last character), Deletechar returns FALSE and the Del-key routine
simply returns without performing any action (this occurrence is not an
error; there is simply no key to delete). If Deletechar returns TRUE,
indicating that the character was successfully deleted, the routine in-
validates the region of the window that displays the altered data.
(Specifically,theinvalidrectangleisassignedthecoordinatesofthepor-
tion of the current line extending from the inserted character to the end
of the line, or to the end of the window if the line extends past the right
border.)
Note that the Del-key routine does not distinguish between the insert
mode and the overwrite mode.

The Ins Key


The Ins-key routine simply toggles the value of the global flag
Insert between 1 and 0, using the following expression:

Insert ^= 1,.
AddingaKeyboardlnterface 263 .

/*** Proce=_3_ Pe_i_key. ***************************************************/


case VK DELETE:

/*** If modifying a new line, must place line in temporary buffer. */


if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)
/*** Delete character from file buffer. ****************************/
if (Deletechar (CursorLine,Cursorcol) )
(
/*** If deletion successful, invalidate window from cursor
position to end of line. *********************************/

Rect.xLeft = (Cursorcol -Firstcol) * xchar;


Rect.xRight = min
((GetLineLength (CursorLine) + 1 -Firstcol) * xchar,
xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
WinlnvalidateRect /* Invalidate region to be updated. */
( hwnd ,
&Rect,
FALSE) ;

Winupdatewindow (hwnd); /* Force client window update. */


)
return TRUE;

• Figure 6.19..
The Del-key routine

As mentioned earlier in the chapter, when this flag is 1, the program


is in the insert mode, and when it is 0, it is in the overwrite mode. Since
Insert is initialized to 1, the program begins in the insert mode. All
routines within the program that depend upon the state of this mode
directly test Insert (for example, the Backspace-key routine, described
in the previous section). Note that the version of the program presented
in Chapter 7 will allow you to select modes through a menu item; in this
version, Ins will be designated as an ¢cccJcr#£or key (explained in Chap-
ter 7) and will be processed directly by the menu routine rather than
through the VirtKey function.
• 264 Programmer's Guide to the os/2PresentationManager

int Deletechar /* Deletes a character from 'LineBuffer'.


(SHORT Line, /* Line containing character to be deleted.
SHORT Column) /* Number of character to be deleted.
/*
This function deletes the indicated character from 'LineBuffer'. It
returns TRUE if the buffer was modified, and FALSE if no action took
place (i.e., the specified character was beyond the visible end of the
line) .
*/
(
/*** Return FALSE if character is beyond visible length of line. *************/
if (LineTable [Line].LineLength < 3 I I
Column > LineTable [Line].LineLength -3)
return FALSE;

/*** Move all characters beyond deleted character one place left. ************/
memmove
(LineBuffer + Column, /* Target.
LineBuffer + Column + 1, /* Source.
LineTable [Line].LineLength -Column -1) ; /* Number of bytes.

/*** Adjust line length. *****************************************************/


--LineTable [Line].LineLength;

return TRUE;

} /* end Deletechar */

• Figure 6.20..
The function Deletechar of the example program

• EDITINGANEWFILE
Since the current version of the example program allows you to
add data to the file, it should permit opening a new file. Consequently,
if you specify a file name on the command line when starting the pro-
gram, this file is read into the buffer as in the previous version. How-
ever, if you do not specify a file name, then rather than terminating with
an error message, the current version of the program calls the function
NewFile, belonging to the buffer-management module and listed in
Figure 6.21.
NewFile initializes the buffer for a new empty file. It allocates a heap
having an initial size of 4096 bytes; remember, however, that the Presen-
tation Manager will automatically expand the heap if it requires more
memory to satisfy an allocation request.
AddingaKeyboardlnterface 265 .

void NewFile (void)


/*
Initializes the file buffer for a new empty file.
*/
(
PCH Farptr; /* Temporary far character pointer. */
/*** Initialize 'LineBuffer'. ************************************************/
LineBuffer [0] = '\n';
LineBuffer [1] = '\0';

/*** Initialize 'LineTable' for first (and only) line. ***********************/


LineTable [0].LineAddress = MAKEP (Lineselector, Lineoffset) ;
LineTable [0] .LineLength = 2;

/*** Initialize 'LastLine'. **************************************************/


LastLine = 0;

/*** Create a heap to hold data added to file. *******************************/


HHeap = WincreateHeap
(0, /* Segment address: 0 means allocate new segment.
4096, /* Initial heap size.
0, /* Minimum increase size: 0 means use default.
0, /* Minimum # of dedicated free lists: none.
0, /* Maximum # of dedicated free lists: none.
HM MOVEABLE) ; /* Options: support movable objects.

/*** Obtain selector address of heap. ****************************************/


Farptr = WinLockHeap (HHeap) ;
Heapselector = SELECTOROF (Farptr) ;

) /* end NewFile */

• Figure 6.21..
The function NewFIle of the example program

• ENHANCEMENTS
This section offers three suggestions for enhancements to the
present version of the example program:

• Using inline code for displaying single characters


• Eliminating trailing blanks
• Converting tab characters
• 266 Programmer's Guide to the os/2 Presentation Manager

Inline Display Code


One of the design goals of the example program is to centralize all
code for painting the window within a s!.7igJc rot/£z.77c. As you have seen
in this chapter, all updating of the characters displayed in the window
occurs through the Paint function, which processes the WM_PAINT
message. When any other routine in the system needs to modify the
window data, it simply invalidates the appropriate section of the win-
dow, which forces the system to issue a WM_PAINT message; the func-
tion Paint then obtains the coordinates of the invalid area and displays
the current characters from the file buffer within this area.
Centralizing all display code within a single routine makes the pro-
gram shorter, simpler, and easier to maintain. However, the process of
invalidating a window region and generating a paint message is quite
time-consuming. The time overhead is especially excessive for display-
ing a single character. You can process single characters typed at the end
of the line more efficiently if you place a special duplicate version of the
display code directly within the appropriate routine in the Character
function (the current routine is listed in Figure 6.7). If the character is
not typed at the end of the line and the program is in insert mode, it
is probably best to use the present method, since more than one charac-
ter will have to be displayed.
By locating the code for displaying single characters within the Char-
acter function, you can save the overhead of the function calls to Win-
InvalidateRect,, Winupdatewindow, and Paint, and you can eliminate
the calculation of the start and stop lines and the for loop logic. If you
place the display code within the character-handling routine, however,
you should observe the following general guidelines (except for these
guidelines, the routine can use the same method employed by the Paint
function):

• Obtain and release the presentation space using the winGetps


function (Figure 3.20) and the WinReleaseps function (Figure
3.21), rather than WinBeginpaint and WinEndpaint (which
should be called only during processing of the WM_PAn\IT message).
Hide the cursor before displaying the character, and make it
visible afterward, by calling Winshowcursor (Figure 5.5). Other-
wise, the cursor will not be erased from the character cell, and
AddingaKeyboardlnterface 267 .

multiple copies of the cursor will appear across the window.


(The system automatically performs this task when you call Win-
Beginpaint and WinEndpaint.)
• Rather than explicitly erasing the area to be occupied by the new
character (through WinFillRect), you can call the Presentation
Manager function GpisetBackMix (Figure 9.8), before calling
GpicharstringAt, as follows:
GpisetBackMix (Hpresspace, BM 0VERPAINT) ,.
This function call causes GpicharstringAt to overwrite the back-
ground within the character cell with its default background
color. Otherwise, GpicharstringAt paints only the foreground
pixels and leaves the background unaltered; the result is that the
old character is not erased and the new character is written
directly on top of it. Note that if the default background color is
not the same as the window background (white in the example
program, generated by WinFillRect), you may have to call Gpi-
SetBackcolor (Figure 9.9) to set the background color used by
GpicharstringAt within the specified presentation space.

The length parameter passed to GpicharstringAt should be lL and


the string parameter should be the address of the single character that
was entered (CHARMSG (&msg)->chr). Writing characters using
direct inline code is dramatically faster that the indirect method
employed by the example program, and the difference in speed is espe+
cially noticeable when holding down a character key to generate
repeated keystrokes.

Eliminating Trailing Blanks


When blank characters are entered at the end of a line, these char-
acters are saved in the file buffer and remain there even if the line is not
subsequently terminated with one or more nonblank characters. Since
these terminating blanks waste valuable file space, you might want
to eliminate them when the user moves the cursor away from the cur-
rent line and begins modifying another line. A good point within the
• 268 Programmer's Guide to the os/2 Presentation Manager

program to remove trailing blanks would be in the function Release-


TempBuf, before (or as) the line is copied from LineBuffer to the heap.

Converting Tab Characters


Although the program converts all tab characters entered from the
keyboard into the equivalent number of spaces, and does not insert tabs
into the file buffer, it makes no provision for converting tab characters
contained in a file read into the buffer (such tabs could have been
entered by another editor). GpicharstringAt does not properly display
tabs (they appear as small circles). Therefore, you might want to modify
the ReadFile function to convert tab characters to the appropriate num-
ber of spaces as each line is read from the file.

• CONCLUSION
A MAKE file for preparing the current version of the example pro-
gram is given in Figure 6.22, and the linker definition file is in Figure
6.23. The complete source code listing appears in Figure 6.24.
The example program at its current state of evolution provides most
of the basic editing functions for modifying or creating a text file. The
next logical step is to allow you to save the modified version of the file,
and to perform other file functions such as reading a new file. The file
functions will be accessed through a Presentation Manager menu, and
the file names will be entered through a dialog box. Therefore, although
the routines for performing these operations are simple, they are not in-
troduced until dialog boxes have been added in Chapter 8.

# Figure 6. 22
# This RAKE file prepares the program of Figures 6.23 and 6.24
#
- cl
FIG6 24.OBT : FIG6 - 24.C
/W2 /c /7;p /r:?Ns FTJf 36_24.C
FIG6 24.EXE : -
FIG6 24.OBT FIG6 23.DEF
link /NOD FIG6 24.OBJ,, NUL, OS2.LIB SLIBCE.LIB, FIG6 23.DEF

• Figure 6.22..
A MAKE file for preparing the example program
AddingaKeyboardlnterface 269 .

; Figure 6.23
; Linker, definition file for the program listed in Figure 6.24
NAME FIG6 24
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 6®23..
A linker definition file for preparing the exanple progran

/*
Figure 6.24

Version 4 of the Presentation Manager text editor example program.


This version adds the following features:
o Displays a cursor indicating the current insertion point, which can be
moved with the arrow and Home/End keys
o Permits creating a new f ile as well as reading in an existing f ile
o Allows you to add characters and lines to the file
o Supports both insert and overwrite modes (toggled with the Ins key)
o Backspace and Del keys can be used to delete characters
o Backspace key can be used to join lines
o Ctrl-Y key can be used to delete complete lines
o Tab key is converted to the equivalent number of space characters
*/

#def ine INCL GPI /* Include all Gpi... function declarations. */


#def ine INCL-WIN /* Include all Win... function declarations. */
#include <OSZ.H>
#include <STDIO.H> /* C library header files:
#include <PROCESS.H>
#include <IO.H>
#include <STRING.H>
#include <STDLIB.H>

• Figure 6.24..
The source code file for the example program
• 270 Programmer's Guide to the os/2 Presentation Manager

/*** Window procedure declaration. *******************************************/

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

/*** Declarations / definitions for file-and buffer-management module. ******/


#def ine LINEBUFSIZ /* Size of buffer for holding lines.
#def ine ERROPEN /* Error: opening file.
#def ine ERRT00BIG /* Error: file too large.
#def ine ERRMAXLINES /* Error: maximum file lines exceeded.
#def ine ERRALLOC /* Error: heap allocation.
void Buflnit (void) ; /* Initializes buffer-management module.
/* Deletes character from buffer:
int Deletechar (SHORT Line, SHORT Column) ;
void DeleteLine (SHORT Line) ; /* Deletes the current line.
char *ErrorMessage (int ErrorNumber) ; /* Returns error message string.
PCH GetLineAddr (int Line) ; /* Gets address of line in buffer.
SHORT GetLineLength (int Line) ; /* Gets length of line in buffer.
void GetTempBuf (int Line) ; /* Obtains a temporary line buffer.
/* Inserts character into buffer:
int Insertchar (SHORT Line,USHORT Character,SHORT Column, int Overwrite) ;
/* Inserts new line into buffer.
void InsertLine (SHORT Line, SHORT Column) ;
int JoinLine (SHORT Line) ; /* Joins line to previous line.
void NewFile (void) ; /* Clears buffer for a new file.
int ReadFile (char *FileName) ; /* Reads file into editor buffer.
void ReleaseTempBuf (int Line) ; /* Releases temporary line buffer.
int LastLine = -1; /* Number of last line in buffer.
HHEAP HHeap = NULL; /* PM heap handle.

/*** Utility function declarations. ******************************************/


void ErrorQuit (char *Message) ; /* Print error message, end program. */
void Quit (int Errorcode) ; /* Terminate the PM program. */

/*** Global variables. *******************************************************/

HWND HFrame; /* Handle to main frame window.


HAB HAncBlk; /* Handle to anchor block.
HMQ HMesQue; /* Message queue handle.
char Message [64] ; /* Buffer for displaying error messages.
void main (int argc, char *argv[])
(
int ReadError = 0; /* Error occurred reading file.
HWND Hclient; /* Handle to main client window.
QMSG QueMess; /* Message structure.
ULONG CtlData = /* Control windows to include.
/* Horizontal scroll bar.
/* Minimize/maximize box.
/* Make window visible on screen.
/* Wide sizing border.
/* System menu.

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 271 .

/* Display program name in Task Manager. */


/* Title bar. */
/* Vertical scroll bar. */
Buflnit ();

/*** If no file specified, open a new file. *********************************/


if (argc < 2)
NewFile () ;
else
ReadError = ReadFile (argv [1]) ;
HAncBlk = Winlnitialize (0) ; /* Initialize PM system for process. */
HMesQue = WincreateMsgQueue (HAncBlk,0) ; /* Create a message queue. */
WinRegisterclass /* Register procedure for main window.
(HAncBlk, /* Anchor block handle.
''RAIN„ , /* Window class name.
Wndproc , /* Window procedure associated w/ class.
OL, /* Class style.
0); /* Extra storage bytes.
HFrame = Wincreatestdwindow /* Create parent window.
(HWND DESKTOP, /* Parent wind6w handle.
WS VISIBLE, /* Frame window style.
&c€lData, /* Address of control data.
''mlN„ ' /* Client window class name.
'': PM Text Editor", /* Text for title bar.
OL, /* Client window style.
0, /* Resource module handle.
0, /* Resource identification.
&Hclient) ; /* Address to receive client window hand.
if (ReadError) /* Quit if read error.
ErrorQuit (ErrorMessage (ReadError) ) ;
WinsetFocus /* Give focus to client window.
(HWND DESKTOP, /* Handle for desktop window.
Hclie=t) ; /* Client window handle.
while (WinGetMsg /* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure
0, /* Window filter.
0' /* First message identifier.
0)) /* Last message identifier.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

Quit (0) ; /* Normal termination.


} /* end main */

• Figure 6.24..
The source code file for the example program (continued)
• 272 Programmer's Guide to the os/2PresentationManager

/*** Window procedure and subroutines. *************************************** /


MRESULT Character (HWND hwnd USHORT msg MPARAM mpl
MRESULT Create (HWND hwnd USHORT msg MPAFun mpl
MRESULT HScroll (HWND hwnd USHORT msg MPAF" mpl
MRESULT Paint (HWND hwnd USHORT msg MPARAM mpl
MRESULT SetFocus (HWND hwnd USHORT msg MPARAM mpl
MRESULT Size (HWND hwnd USHORT msg MPAF" mpl
MRESULT VirtKey (HWND hwnd USHORT msg MPARAM mpl
MRESULT Vscroll (HWND hwnd USHORT msg MPARAM mpl

static xchar; /* Character width.


static ycharTot ; /* Total height of characters.
static ycharDesc ; /* Height of character descenders.
static xwin ; /* Horizontal size of window.
static ywin ; /* Vertical size of window.
static HVscrol I ; /* Handle to vertical scroll bar window.
static HHScroll ; /* Handle to horizontal scroll bar window
static int Firstcol; /* Character to be in first column position.
static int FirstcolMax; /* Maximum value of 'Firstcol'.
static SHORT TopLine = 0; /* Number of top line in window.
static SHORT TopLineMax; /* Maximum value of 'TopLine'.
static FATTRS FontAttributes; /* Stores font attributes from GpiQueryFonts
/*** Cursor-management variables. ********************************************/
static SHORT CursorLine = 0; /* Current line location of cursor. */
static SHORT Cursorcol = 0; /* Current column location of cursor. */
static SHORT LastcursorLine = 0; /* Last line position of cursor. */

/*** Flag for insert mode. ***************************************************/


static int Insert = 1;
#define ID COURIER 99L /* Local font ID.

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle. */
USHORT msg, /* The message. */
MPARAM mpl, /* Message-specific information. */
MPAF" mp2) /* Message-specific information. */
(
char Buffer [81] ;
switch (msg)
(
case WM CHAR: /* Message sent when keyboard key is received. */

/*** Don't process a key-released message. *************************/


if (CHARMSG (&msg)->fs & KC KEYUP)
return FALSE;

/*** Process a:1rLarac€er key. ****************************************/


else if (CHARMSG (&msg)->fs & KC CHAR)
return Character (hwnd, msgT mpl, mp2) ;

/*** Process virtual key. ******************************************/


else if (CHARMSG (&msg)->fs & KC VIRTUALKEY)
return VirtKey (hwnd, msg, ripl, mp2) ;

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 273 .

/*** Don't process invalid key. ************************************/


else /* Invalid key: neither virtual nor character.*/
return FALSE;

case WM CREATE: /* Message sent when window is first created. */


return Create (hwnd, msg, mpl, mp2) ;

case WM HSCROLL: /* Message sent on horizontal scroll activity. */


return HScroll (hwnd, msg, mpl, mp2) ;

case WM PAINT: /* Message sent when window data is invalid. */


return Paint (hwnd, msg, mpl, mp2) ;

case WM SETFOCUS: /* Message sent when client focus changes. */


return SetFocus (hwnd, msg, mpl, mp2) ;

case WM SIZE: /* Message sent whenever window changes size. */


return Size (hwnd, msg, mpl, mp2) ;

case WM VSCROLL: /* Message sent on vertical scroll activity. */


ret-urn Vscroll (hwnd, msg, mpl, mp2) ;
default: /* Perform default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;

} /* end switch */
} /* end Wndproc */

/*** Subroutines called by window procedure. *********************************/

MRESULT EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

This function processes character keys (that is, keys with a valid ASCII
code) .
*/

:=g::t=:c::t col; ,: E:::sf::o::::a::sg::e=:::a:::e:haracters. :,


/*** If modifying a new line, must place line in temporary buffer. ***********/
if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)

/*** Process a Backspace key. ************************************************/


if (CHARMSG(&msg)->chr == '\b`)
(
/*** If cursor is at column 0, must join line to previous line. *********/
if (Cursorcol == 0)
(

• Figure 6®24..
The source code file for the example program (continued)
•274 Programmer's Guide to the OS/2 Presentation Manager

/*** NO previous line if cursor is in first line. ******************/


if (CursorLine == 0)
return TRUE;

/*** Move cursor one line up. **************************************/


W±nse?S#:g, /: §:::n:P;::::# #:::::: to self. :/

¥iE;:i::EgEE (5:-¥!:#?;¥;:c:;: re;:i;:I::i:;:::i:: ;;


/*** Move cursor to end of line. ***********************************/
winse?:::g, /: 5:::n:n:i::::ag:n::e:elf. :/

#iE;!!:Egg: (g:-¥!R!;3i#;:c:;: re;:i::!i:!i:ig:;y. ;;


/*** If in overwrite mode, return without joining lines. ***********/
if (!Insert)
return TRUE;

/*** Join line to previous line. ***********************************/


if (!JoinLine (CursorLine + 1))
(
/*** Sound alarm if join fails (max line length exceeded) . ****/
WinAlarm (HWND DESKTOP, WA ERROR) ;
• return TRUE;
)

/*** Adjust 'LastcursorLine'. **************************************/


LastcursorLine = CursorLine;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;

WinsendMsg /* Send message to vertical scroll bar.


(HVscroll, /* Recipient handle.
?BfE3E:?:33!L?3:;Line, o) , /* Se;*ps::::::n: range.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable only scroll possible.


(HVscroll, /* Recipient handle.
TopLineMax ? 1 : 0); /* Enable only if max. != 0.

/*** Invalidate joined line and all lines below. *******************/


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;

WinlnvalidateRect /* Invalidate section to be modified. */


(hwnd, /* Handle of client window. */
&Rect, /* Rectangle to be added to invalid region. */
FALSE) ; /* Don't include descendants w/ WS CLIPCHILDREN*/

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 275 .

/*** Force window update. ******************************************/


Winupdatewindow (hwnd) ;

/*** TRUE signals that key was processed. **************************/


return TRUE;

} /* end cursor at column 0 */


/*** Remaining code is for cursor NOT at column 0. **********************/

/*** Move cursor back one space. ****************************************/


wLnse#:;§§:§E8:: t5:_¥:R:¥£:¥¢; , ::;;:::;::;::;::::::;:::;: Self :j

/*** If in insert mode, delete character. *******************************/


|f(I:::::is::!£:E8::(::-?:Ri::i::;;¥::::;;:;:i:i;;:;::e

/*** If in overwrite mode, overwrite current character with a space. ****/


else
(
/*** Print a space character. **************************************/
wLnse#::§§:i:8R: t¥::::=: ::i:e::;;::;::::::::;:;::o self ;;

/*** Restore cursor position (printing space advanced it!) . ********/


wlnse#!:;!i::E8E: (5:i¥::::£::i:i::;:::;::;:::::ii::;::::e ;;

} /* end overwrite mode */


/*** Signal system that key was processed. *******************************/
return TRUE;

) /* end '\b' */
/*** Process a Tab key by sending equivalent number of space characters. *****/
if (CHARMSG(&msg)->chr == '\t')
(
Col = 5 -Cursorcol % 5;
while (Col--)

• Figure 6.24..
The source code file for the example program (continued)
• 276 Programmer's Guide to the os/2PresentationManager

WinsendMsg /* Send space character message to self .


( hwnd , /* Client window handle.
WM CHAR, /* Character message.
MPFROM2SHORT (KC_CHAR,1) , /* Character key.
MPFROM2SHORT (I ',0)) ; /* Space character
return TRUE;

) /* end '\t' */
/*** Process ET\+er key. ******************************************************/

if (CHARMSG(&msg)->chr == '\r')
(

/*** If in insert mode, insert a new line into buffer. ******************,'


if (Insert)
(
/*** Insert the line into file buffer. *****************************/
InsertLine (CursorLine, Cursorcol) ;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;

WinsendMsg /* Adjust scroll bar range.


(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFEOM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable only if scroll possible.


(HVscroll, /* Recipient handle: vertical scroll bar.
TopLineMax ? 1 : 0); /* Enable only if max. != 0.

/*** Invalidate 'CursorLine' and all lines below. ******************/


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
WinlnvalidateRect
( hwnd ,
&Rect ,
FALSE) ;

/*** Force update of client window. ********************************/


Winupdatewindow (hwnd) ;

} /* end insert mode */


/*** Move cursor down one line. *****************************************/
WinsendMsg /* Move cursor down. */
(hwnd, /* Client window handle. */
WM CHAR, /* Character received message. */
MPFROM2SHORT (KC_VIRTUALKEY,1) ,
MPFROM2SHORT (0, VK DOWN)) ;

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 277 .

/*** Adjust 'LastcursorLine' if in insert mode. *************************/


if (Insert)
LastcursorLine = CursorLine;

/*** Move cursor to beginning of line. **********************************/


----- #!;§fa§E8£=
WinsendMsg ( 5:_¥ER:g£:¥i; , ::;:::t;:n§§:::ii§:§§:::ge
/* Send Horn? fey mes=ige to self. :/
*/
*/
*/
*/
return TRUE;

} /* ervii `\r' */

/*** Process all remaining character keys. ***********************************/

/*** Insert key into file buffer. ********************************************/


if (!Insertchar
( CursorLine ,
CHARMSG ( &msg) ->chr ,
Cursorcol ,
Insert) )
(
/*** Beep if insertion failed (max buffer length exceeded) . *************/
WinAlarm (HWND DESKTOP, WA_ERROR) ;
return TRUE;
)

/*** Invalidate window from cursor position to end of line (or window) . ******/
Rect.xLeft = (Cursorcol -Firstcol) * xchar;
Rect.xRight = min ((GetLineLength (CursorLine) -Firstcol) * xchar, xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
wLn|n!i:§§;:eRect ;: i;;i:::i:::i::::;i::i::;s:;;:;;;:;:g:£:iDREN:;

Winupdatewindow (hwnd) ; /* Force updating of client window. */

/*** Move the cursor right one column. ***************************************/


wLnse#;:i:i:§E:::t5:_¥:R:¥%:¥;f;1,{::::::::::::::::::::::::toseLf

return TRUE;

} /* end Character */

• Figure 6.24:
The source code file for the example program (continued)
• 278 Programmer's Guide tothe os/2Presentation
Manager

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

¥3ST#:;:=88a£:€rics; /: ;:=::::::i:: ::::ef:::d::iensions.


LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts.
GpiLoadFonts /* Load Courier font.
(HAncBlk, /* Anchor block handle.
"\\OS2\\DLL\\COURIER.FON"); /* Full path name of font file.
Hpresspace = WinGetps (hwnd) ;

GpiQueryFonts /* Obtain information on Courier font.

i:::::::i::, ;; ::;:::::: ;::::::a::::s:pace.


&Numberstructs, /* Number of FONTMETRICS structures returned
(long)sizeof (FONTMETRICS) ,/* Length of structure for EACH font.
&Metrics) ; /* Address of FONTMETRICS structure(s).

xchar = (SHORT)Metrics. IAvecharwidth;


ycharTot = (SHORT)Metrics. IMaxBaselineExt;
ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (FontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes.IMatch = Metrics.IMatch;
strcpy (FontAttributes. szFacename,Metrics. szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes. IAvecharwidth = Metrics. IAvecharwidth;
FontAttributes.fsType = FATTR TYPE FIXED;
FontAttributes. fsFontuse = 0;
WinReleaseps (Hpresspace) ;

HHScroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT,FALSE) , /* Handle to parent */
/* window (frame). */
FID HORZSCROLL) ; /* Identifier for vertical scroll bar. */
HVscroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW PARENT,FALSE) , /* Handle to parent */
/* window (frame). */
FID VERTSCROLL) ; /* Identifier for vertical scroll bar. */
return FALSE;

} /* end Create */

MRESULT EXPENTRY HScroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SHORT Delta; /* Amount to scroll.

• Figure 6.24..
The source code file for the example program (continued)
Adding a Keyboard Interface 279.

/*** Determine amount to scroll. **„*„„„„*„"„„*"*„*„„„„***„*/


switch (SHORT2FROMMP (mp2) )
(
case SB LINELEFT:
Delta --1;
break;
case SB LINERIGHT:
Delta -1;
break;
case SB PAGELEFT:
Delta --6;
break;
case SB PAGERIGHT:
Delta -6;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -Firstcol;
break;
default :
Delta -0;
break;
)
Delta = max (-Firstcol, min (Delta,FirstcolMax -Firstcol)) ;
if (Delta)
(
Firstcol += Delta;
/*** Update cursor column. **********************************************/
Cursorcol += Delta;

/*** H±dLe t:he cursor. ***************************************************/


Winshowcursor
( hwnd '
FALSE) ; /: S±i:n:tY±ndow handle. :/
Winscrollwindow /* Scroll the window data.
( hwnd , /* Handle of client window.
-Delta * xchar, /* Horizontal scroll amount.
0, /* Vertical scroll amount.
0, /* Must be 0.
0' /* Must be 0.
0, /* Must be 0.
0' /* Must be 0.
SW INVALIDATERGN) ; /* Invalidate "exposed" region.
Winupdatewindow /* Force updating of client window.
(hwnd) , /* Handle of client window.
WinsendMsg * Adjust horizontal slider position.*
(HHScroll,
* Handle to horizontal scroll bar. *
SBM SETPOS, * Set position of slider.
MPFkoM2SHORT (Firstcol, O) /* Current position.
0); /* Second parameter: n/a.

® Figure 6.24..
The source code file for the example program (continued)
• 280 Programmer's Guide to the os/2Presentation
Manager

/*** Restore cursor to correct position. ********************************/


Wincr?::::?rsor /: §::e£:S:::::w°£a::::?r.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position.
0, /* x size of cursor: n/a.

#::9? sETPoS ' j: k::::n::r::::;::::!:jaon|y.


/*** Show the cursor again. *********************************************/
Winshowcursor
( hwnd ' /* Client window handle.
TRUE) ; /* Show it!
} /* end if (Delta) */
return FALSE;

} /* end HScroll */

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPA~ mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Holds coordinates of rectangle.
SHORT StartLine; /* First file line to paint.
SHORT StopLine; /* Last line to paint.
POINTL Start; /* Starting position to print string.
SHORT LineLength; /* Length of each line displayed.
Hpresspace = WinBeginpaint
(hwnd, * Window handle. */
0' * Handle of PS to have clipping region set. */
&Rect) ; * Address of struct. to set to invalid region.*/
GpicreateLogFont Create a logical font for presentation space*/
( Hpresspace ,
( PSTR8 ) NULL , :::::::a:::: ::::? E:::?e. :/
ID COURIER, Local font ID: define a constant. */
&F6ntAttributes) Struct. specifying font from GpiQueryFonts. */
Gpisetcharset Make logical font the current character set.*/
( Hpresspace ,
ID COURIER) ; :::::n:::E°:D:Pace handle. :/
WinFillRect
( Hpresspace ,
&Rect,
CljR WHITE) ;
/: :::::::::i::n:::::n:a::::;w coordinates. :/
/* Color to use (white). */
Gpisetcolor
( Hpresspace , /* Presentation space handle.
CLR BIACK) ; /* Color to use: black.

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 281 .

StartLine = TopLine + (ywin - (SHORT)Rect.yTop) / ycharTot;


StopLine = min (LastLine, TopLine + (ywin -(SHORT)Rect.yBottom)
/ ycharTot) ;
Start.y = ywin -ycharTot * (StartLine -TopLine + 1) + ycharDesc;
Start.x = xchar * (-Firstcol) ;
for (Line = StartLine; Line <= StopLine; ++Line, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue ;
GpicharstringAt Prints string at given position
( Hpresspace , Presentation space handle.
&Start' Structure cont-aining starting position.
( LONG ) LineLength , Number of characters to print
GetLineAddr (Line) ) Address of line.
)

WinEndpaint (Hpresspace) ;

return FALSE;

) /* end paint */

MRESULT EXPENTRY SetFocus (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** If client window is RECEIVING focus, create cursor. *********************/
if (LONGFROMMP (mp2) )

viincreatecursor /* Create a new cursor


{€::::rco| -Firstco|) * ±:h::lent 7±n:°;o:::€::.of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, __ /*
_ ___ y
_ ._ _ position
I L _ ._I _ `.
0, /* x size of cursor: nominal border
ycharTot, /* y size of cursor.
CURSOR SOLID /* Solid cursor.
CURSOR-FIASH /* Blinking cursor.
NULL) ; /* Clipping rectangle: entire window

/*** Make the cursor visible. *******************************************/


winshi¥§::;Or /: §:::n:tTindow handle. :/

)
/*** If client window is LOSING focus, destroy the cursor. *******************/
else
WinDestroycursor (hwnd) ;
return FALSE;

} /.t end SetFocus */

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
int Update -0;
ywin = SHORT2FROMMP (mp2) ;
xwin = SHORTIFROMMP (mp2) ;

• Figure 6.24:
Tfie source code file for the example program (continued)
®282 Programmer's Guide to the OS/2 Presentation Manager

/*** Scroll window if necessary so that cursor position is visible. **********/


if (CursorLine >= TopLine + ywin / ycharTot)
(
TopLine = CursorLine -ywin / ycharTot + 1;
Update -1;
)
if (Cursorcol > Firstcol + xwin / xchar - 1)
(
Firstcol = Cursorcol -xwin / xchar + 1;
Update -1;
)
if (update)
WinlnvalidateRect
( hwnd , /* Client window handle.
0, /* Rectangle: 0 means whole window.
FALSE) /* Do not automatically include children
/*** If client has focus, must RE-CREATE the cursor for new size. ************/
if (hwnd == WinQueryFocus /* Does client have focus?

£ATyLgETPESKT°P , ,: E:S:o:±¥:cfe:::::wpandLe.
(
/*** Destroy existing cursor. *******************************************/
WinDestroycursor (hwnd) ;

/*** Create
-_,_
new cursor. **********************************************„*/
Wincreatecursor /* Create a new cursor. */
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position
0' /* x size of cursor: nominal border.
ycharTot, /* y size of cursor.
CURSOR SOLID /* Solid cursor.
CURSOR-FIASH /* Flashing cursor.
NULL) ; /* Clipping rectangle: entire window.
/*** Display the cursor. ************************************************/
Winshowcursor
(hwnd, /* Client window handle.
TRUE) ; /* Show it!
)

TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;


TopLine = min (TopLine,TopLineMax) ;

WinsendMsg /* Adjust range/position of slider.


(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFEOM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable scroll bar if scrolling is possible.


(HVscroll, /* Recipient handle: vertical scroll bar.
TopLineMax ? TRUE : FALSE) ; /* Enable only if max. != 0.

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 283 .

FirstcolMax = LINEBUFSIZ -2 -xwin / xchar;


Firstcol = min (Firstcol, FirstcolMax) ;
W±nse?S¥SgroL] , /: a:±¥;:e=:ng:4£::?ti:=i::n::±d::loll bar;(
SBM SETSckoLLBAR, /* Set position & range
MPFEOM2SHORT (Firstcol, 0) , /* position
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range.

return FALSE;

} /* end Size */

MRESULT EXPENTRY VirtKey (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
RECTL Rect; /* Holds coordinates of rectangle.
SHORT NewFirstcol ; /* Temporary storage for new first column pos
SHORT Newcursorcol ; /* Temporary storage for new cursor column.
int Update; /* Flag indicating window update needed.

/*** Branch according to virtual key code. ***********************************/


switch (CHARMSG (&msg) ->vkey)
(
/*** ±rocess up-arrow key. **********************************************/
case VK UP:

/*** If cursor at top of window, scroll up. ************************/


if (CursorLine == TopLine)
(
WinsendMsg /* Scroll window one line up.
*/
( hwnd ,
" VSCROLL,
OL'
MPFROM2SHORT (0,SB LINEUP) ) ;
return TRUE;
)
/*** If cursor NOT at top, simply adjust 'CursorLine'. *************/
else
--CursorLine ;
break;
/*** Process down-arrow key. ********************************************/
case VK DOWN:

/*** If cursor at end of file, simply return. **********************/


if (CursorLine == LastLine)
return TRUE;

/*** If cursor is in bottom line of window, scroll down. ***********/


else if (CursorLine == TopLine + ywin / ycharTot - 1)
(
WinsendMsg

• Figure 6®24..
The source code file for the example program (continued)
• 284 Programmer's Guide to the os/2 Presentation Manager

( hwnd '
WM VSCROLL,
OL'
MPFROM2SHORT (0,SB LINEDOWN) ) ;
return TRUE;
)
/*** Otherwise, simply adjust 'CursorLine'. ************************/
else
++CursorLine ;
break;
/*** Proce=_5_ ±e_i_€_-arrow key. ********************************************/
case VK LEFT:

/*** If cursor is at left of window, scroll left. ******************/


if (Cursorcol == Firstcol)
(
WinsendMsg
( hwnd ,
" HSCROLL,
OL'
MPFROM2SHORT (0,SB LINELEFT) ) ;
return TRUE;
)
/*** Otherwise, simple adjust 'Cursorcol'. *************************/
else
--Cursorcol ;
break;
/*** Process r±qtL+-arrow key. *******************************************/
case VK RIGHT:

/*** If cursor is at right of window, scroll to right. *************/


if (Cursorcol == Firstcol + xwin / xchar - 1)
(
WinsendMsg
(hwnd,
WM HSCROLL,
OL,
MPFROM2SHORT (O,SB LINERIGHT) ) ;
return TRUE;
)
/*** Otherwise, simply adjust 'Cursorcol'. *************************/
else
++Cursorcol ;

break;
/*** Process Page Up key. ***********************************************/
case VK PAGEUP:
Wi=SendMsg /* Send scroll page-up message to self . */
( hwnd ,
" VSCROLL,
OL,
MPFROM2SHORT (0,SB PAGEUP) ) ;

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 285 .

return TRUE;

/*** ProceE5s Page Down key. *********************************************/


case VK PAGEDOWN:
WiHsendMsg /* Send scroll page-down message to self . */
( hwnd ,
" VSCROLL,
OL,
MPFROM2SHORT (0,SB_PAGEDOWN) ) ;
return TRUE;

/*** Process Hone key. **************************************************/


case VK HOME:

/*** Scroll if beginnings of lines not visible. ********************/


if (Firstcol != 0)
(
WinsendMsg /* Send scroll to absolute position */
/* message to self. */
( hwnd '
" HSCROLL,
OL,
MPFROM2SHORT (0,SB_SLIDERPOSITION) ) ;
)

Cursorcol = 0;
break;

/*** process End key`. ***************************************************/


case VK END:

/*** Set temporary cursor position to end of line. *****************/


Newcursorcol = (int)GetLineLength (CursorLine) ;

/*** clear update £Laq. ********************************************/


Update -0;

/*** End of line to right of portion visible in window. ************/


if (Newcursorcol > Firstcol + xwin / xchar - 1)
(
NewFirstcol = Newcursorcol -xwin / xchar + 1;
Update = 1,
)
/*** End of line to left of portion visible in window. **************/
else if (Newcursorcol < Firstcol)
(
NewFirstcol = Newcursorcol;
Update -1;
)
/*** Scroll window if end of line not visible. *********************/
if (Update)
WinsendMsg
( hwnd ,
WM HSCROLL,

• Figure 6.24..
The source code file for the example program (continued)
• 286 Programmer's Guide to the os/2 Presentation Manager

OL,
MPFROM2SHORT (NewFirstcol,
SB SLIDERPOSITION) ) ;

/*** Set permanent cursor column position. *************************/


Cursorcol = Newcursorcol;
break ;
/*** Process Del key. ***************************************************/
case VK DELETE:

/*** If modifying a new line, must place line in temporary buffer. */


if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)
/*** Delete character from file buffer. ****************************/
if (Deletechar (CursorLine,Cursorcol) )
(
/*** If deletion successful, invalidate window from cursor
position to end of line. *********************************/

Rect.xLeft = (Cursorcol -Firstcol) * xchar;


Rect.xRight = min
((GetLineLength (CursorLine) + 1 -Firstcol) * xchar,
xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
WinlnvalidateRect /* Invalidate region to be updated. */
(hwnd,
&Rect ,
FALSE) ;

Winupdatewindow (hwnd) ; /* Force client window update. */


)
return TRUE;

/*** Process Ins key by toggling 'Insert' flag. *************************/


case VK INSERT:
In=ert `-1;
return TRUE;

/*** Process F9 key: delete line containing cursor. ********************/


case VK F9:

/*** If modifying a new line, must place line in temporary buffer. */


if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 287 .

/*** Delete line containing the cursor. ****************************/


DeleteLine (CursorLine) ;

/*** Adjust 'TopLineMax' and scroll bar range for new file length. */
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
WinsendMsg
(HVscroll , /* Recipient handle.
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (TopLine, 0) , /* position.
MPFROM2SHORT (0, TopLineMax)) ; /* Range .
WinEnablewindow
(HVscroll , /* Recipient handle.
TopLineMax ? 1 : 0); /* Enable only if max. !=

/*** Invalidate 'CursorLine' and all lines below. ******************/


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
WinlnvalidateRect /* Invalidate section to be modified.
£R:::; ,: E:::::g:: ::i::tag:::o¥; invalid region
FALSE) ; /* No descendants w/ WS_CLIPCHILDREN.

Winupdatewindow (hwnd) ; /* Force updating of client window. */


return TRUE;

/*** For all other keys, return FALSE indicating key not processed. *****/
default:
return FALSE;

} /* end virtual key switch */


/*** Update cursor position for all cases above that altered 'CursorLine' or
`cursofrco±` . *****************************************************************/

Wincreatecursor /* Set position of cursor.


(=:=:6rco| -Firstco|) * xchar/* CLLe7: ¥±:::¥t:::d::.cursor
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position
0, /* x size of cursor: n/a.
0' /* y size of cursor: n/a.
CURSOR SETPOS , /* Option to set position only.
NULL) ; /* Clipping rectangle: n/a
return TRUE;

} /* end VirtKey */

mESULT EXPENTRY Vscroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SHORT Delta; /* Amount to scroll.

• Figure 6®24..
The source code file for the example program (continued)
•288 Programmer's Guide to the OS/2 Presentation Manager

/*** Determine amount to scroll. *********************************************/

switch (SHORT2FRormp (mp2)) /* Switch on code from scroll bar.


(
case SB LINEUP:
Delta --1;
break;
case SB LINEDOWN:
Delta -1;
break;
case SB PAGEUP:
Delta = -ywin / ycharTot;
break;
case SB PAGEDOWN:
Delta = ywin / ycharTot;
break;
case SB SLIDERPOSITION:
Delta SHORTIFROMMP (mp2) -TopLine;
break;
default:
Delta -0;
break;
)
Delta = max (-TopLine, min (Delta,TopLineMax -TopLine)) ;

if (Delta)
(
TopLine += Delta;

/*** Update cursor line. ************************************************/


CursorLine += Delta;

/*** Hide the cursor. ***************************************************/


Winshowcursor
( hwnd , /* Client window handle.
FALSE) ; /* Hide it!
Winscrollwindow
( hwnd , /* Handle of client window.
0, /* Horizontal scroll amount.
ycharTot * Delta, /* Vertical scroll amount.
0, /* Must be 0.
0' /* Must be 0.
0' /* Must be 0.
0, /* Must be 0.
SW INVALIDATERGN) /* Invalidate "exposed" region.
Winupdatewindow
(hwnd) ; /* Handle of client window.
WinsendMsg
(HVscroll, /* Handle to vertical scroll bar.
SBM SETPOS, /* Set position of slider.
MPFROM2SHORT (TopLine,0) ,/* Current position.

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 289 .

0) ; /* Second parameter n/a. */

/*** Restore cursor to correct position. ********************************/


Wincreatecursor /* Set position of cursor.
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine -TopLine + 1) * ycharTot, /* y position.
0, /* x size of cursor: n/a.
0, /* y size of cursor: n/a.
CURSOR SETPOS /* Option to set position only.
NULL) ; /* Clipping rectangle: n/a
/*** Show the cursor again. *********************************************/
Winshowcursor
( hwnd , /* Client window handle. */
TRUE) ; /* Show it! */
} /* end if (Delta) */
return FALSE;

} /* end Vscroll */

/*** Buffer-management module ************************************************/

#define MAXLINES 4096 /* Maximum number of lines in file buffer.*/


static struct /* Stores information on each line. */
(
PCH LineAddress; /* Far address of block containing line. */
unsigned char LineLength; /* Length of line (includes \n and \0). */
)
LineTable [RAXLINES] ;

static char LineBuffer [LINEBUFSIZ] ; /* Temporary line buffer.


static unsigned Lineselector; /* Selector for 'LineBuffer'.
static unsigned Lineoffset; /* Offset for 'LineBuffer'.
static SEL Heapselector; /* Selector of heap segment.

void Buflnit (void) /* Initializes the buffer-management module.


(
PCH Farptr;

Farptr = (char far *)LineBuffer;


Lineselector = SELECTOROF (Farptr) ;
Lineoffset = OFFSETOF (Farptr) ;

} /* end Buflnit */

int Deletechar /* Deletes a character from 'LineBuffer' .


(SHORT Line, /* Line containing character to be deleted.

• Figure 6.24..
The source code file for the example program (continued)
• 290 Programmer's Guide to the os/2PresentationManager

SHORT Column) /* Number of character to be deleted. */


/*
This function deletes the indicated character from 'LineBuffer'. It
returns TRUE if the buffer was modified, and FALSE if no action took
place (i.e. , the specified character was beyond the visible end of the
line) .
*/
(
/*** Return FALSE if character is beyond visible length of line. *************/
if (LineTable [Line].LineLength < 3 I I
Column > LineTable [Line].LineLength -3)
return FALSE;

/*** Move all characters beyond deleted character one place left. ************/
memmove
(LineBuffer + Column, /* Target.
LineBuffer + Column + 1, /* Source.
LineTable [Line].LineLength -Column -1) ; /* Number of bytes.

/*** Adjust line length. *****************************************************/


--LineTable [Line].LineLength;

return TRUE;

} /* end Deletechar */

void DeleteLine (SHORT Line)

Deletes the specified line ('Line' , which must be the line currently
containing the cursor) from the file buffer.
(
/*** If line to be deleted is the last file line, merely truncate it. ********/
if (Line == LastLine)
(
LineBuffer [0] = '\n';
LineBuffer [1] = '\0';
LineTable [Line].LineLength = 2;
)
else
(
/*** Place the following line into 'LineBuffer'. ************************/
GetTempBuf (Line + 1) ;

/*** Move all LineTable elements beyond deleted line down one element. **/
memmove

!i::::::E:e [i:::el,1] , /: g::::::


(LastLine -Line) * sizeof (LineTable [0])) ; /* Number bytes

/*** Adjust 'LastLine'. **************************************************/


--LastLine ;
)

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 291 .

} /* end DeleteLine */

char *ErrorMessage (int ErrorNumber)


/*
Returns a string that describes the error code given by 'ErrorNumber' .
*/
(
static char *MessageTable [] =
(
''no error",
''file open failure",
'°file too large",
'°maximum lines exceeded",
"heap memory allocation failed",
''unidentif led error''
);

if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))


ErrorNumber = sizeof (MessageTable) / sizeof (char *) -1;
return MessageTable [ErrorNumber] ;

} /* end ErrorMessage */

PCH GetLineAddr (int Line)


/*
Returns the address of the file buffer line specified by 'Line' .
*/
(
if (Line < 0 I I Line > LastLine)
return NULL;
else
return LineTable [Line] .LineAddress;

} /* end GetLineAddr */

SHORT GetLineLength (int Line)


/*
Returns the length of the file buffer line specified by 'Line' .
*/
(
if (Line < 0 I I Line > LastLine)
return 0;
else
return LineTable [Line] .LineLength -2;
} /* end GetLineLength */

void GetTempBuf /* Places specified line into 'LineBuffer'.


(int Line) /* Number of line.
/*

• Figure 6.24..
The source code file for the example program (continued)
• 292 Programmer's Guide to the os/2PresentationManager

This function:
o Copies the string in the specified line into 'LineBuffer'
o Frees the block formerly holding the string
o Adjusts the address in 'LineTable'
*/
(
/*** Copy string into 'LineBuffer'. ******************************************/
movedata /* Intersegment block copy.*/
(SELECTOROF (LineTable[Line].LineAddress) , /* Source segment. */
OFFSETOF (LineTable[Line].LineAddress) /* Source offset. */
Lineselector , /* Target segment. */
Lineof fset , /* Target offset. */
LineTable [Line] .LineLength) ; /* p;rytes to copry. */
/*** Release block formerly holding line. ************************************/
if (WinFreeMem
(HHeap, /* Handle of heap from 'WincreateHeap' .
(BYTE NEAR *)OFFSETOF (LineTable [Line].LineAddress) , /* Offset.
LineTable [Line].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message, "managing heap; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

/*** Place new address into 'LineTable'. *************************************/


LineTable [Line] .LineAddress = MAKEP (Lineselector,Lineoffset) ;

} /* end GetTempBuf */

int Insertchar /* Inserts character into 'LineBuffer'


(SHORT Line, /* Number of line for insertion.
USHORT Character, /* Character to insert.
SHORT Column, /* Column position of character.
int Insert) /* Flag indicating overwrite mode.
(
unsigned char LineLength;

/*** Obtain the length of the line. ******************************************/


LineLength = LineTable [Line] .LineLength;

/*** If line would exceed maximum line length, return without inserting. *****/
if (Column > LINEBUFSIZ - 3 I I LineLength >= LINEBUFSIZ && Insert)
return FALSE;

/*** If column is at end of line (common case) , use fast routine to insert. **/
else if (Column == LineLength -2)
(
/*** Copy '\n' and '\0' to new position. ********************************/
LineBuffer [Column + 2] = LineBuffer [Column + 1];
LineBuffer [Column + 1] = LineBuffer [Column];

/*** Write the character. ***********************************************/


LineBuffer [Column] = (char)Character;

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 293 .

/*** Adjust line length. ************************************************/


++LineTable [Line].LineLength;
return TRUE;
)

/*** If column is BEYOND end of line, must pad line with spaces. *************/
else if (Column > LineLength -2)
(
/*** Copy '\n' and '\0' to new position. ********************************/
LineBuffer [Column + 2] = LineBuffer [LineLength -1];
LineBuffer [Column + 1] = LineBuffer [LineLength -2];

/*** Fill line with spaces. *********************************************/


memset
(LineBuffer + LineLength -2, /* Destination. */
:oiLmn -LineLength + 2) ; /: S=::::t:: ::p:i±:i:i:?. :/
/*** Write character. ***************************************************/
LineBuffer [Column] = (char)Character;

/*** Adjust line length. ************************************************/


LineTable [Line].LineLength = (unsigned char)Column + 3;
return TRUE;
)
/*** Otherwise, must insert character in middle of line. *********************/
else
(
/*** If insert mode is active, move all characters right of insertion
point one space to the right. **************************************/
if (Insert)
(
memmove /* Move block.
(LineBuffer + Column + 1, /* Target.
LineBuffer + Column, /* Source.
LineLength -Column); /* Number of bytes.
/*** Adjust line length. *******************************************/
++LineTable [Line].LineLength;
)
/*** Write character. ***************************************************/
LineBuffer [Column] = (char)Character;
return TRUE;
)

} /* end Insertchar */

void InsertLine (SHORT Line, SHORT Column)


/*
Inserts a new line into the file buffer, immediately before character
given by 'Column' , within the line given by 'Line' .
*/
(

• Figure 6.24..
The source code file for the example program (continued)
• 294 Programmer's Guide to the os/2 Presentation Manager

NPCH Heapoffset; /* Holds 16-bit heap offset. */


PCH Heappointer; /* Holds far pointer to heap base. */
/*** Fatal error if maximum lines reached. ***********************************/
if (++LastLine >= MAXLINES)
(
sprintf (Message,"maximum lines reached; line %d", LINE_) ;
ErrorQuit (Message) ;
)

/*** Adjust 'Column' to maximum position in line. ****************************/


if (Column > LineTable [Line].LineLength -2)
Column = LineTable [Line].LineLength -2;

/*** Allocate a block for characters in line before 'Column' . ****************/


Heapof fset = WinAllocMem
(HHeap,
Column + 2) ;
if (Heapof fset == NULL)
(
sprintf (Message,"out of heap memory; line %d", LINE_) ;
ErrorQuit (Message) ;
)

/*** Copy characters before 'Column' into new block. *************************/


movedata /* Intersegment block copy. */
( Lineselector , /* Source: selector of 'LineBuffer' */
Lineoffset, /* Source: offset of 'LineBuffer' . */
Heapselector , /* Target: selector of heap. */
(unsigned)Heapoffset /* Target: offset of new block. */
Column) ; /* Number of characters to copy. */

/*** Construct a far pointer to new block in heap. ***************************/


Heappointer = MAKEP (Heapselector,Heapoffset) ;

/*** Write newline and null to end of new line in heap. **********************/
*(Heappointer + Column) = '\n' ;
*(Heappointer + Column + 1) = '\0';

/*** Move character number 'Column' and all following characters to beginning
o£ `L±neBu££er` . ********************************************************/
memmove /* Intrasegment block copy. */
i:::::¥=::r+ co|umnJ /: :::::: :::=:::: :/
LineTable [Line].LineLength -Column) ; /* Bytes to move. */

/*** Adjust line length. *********-********************************************/


LineTable [Line].LineLength -= (unsigned char)Column;

/*** Move all members of 'LineTable' one position toward end of table. *******/
memmove
(&LineTable [Line + 1], /* Target.
&LineTable [Line] , /* Source.
(LastLine -Line) * sizeof (LineTable [0])); /* Bytes to move.

• Figure 6.24..
The source code file for the example program (continued)
AddingaKeyboardlnterface 295 .

/*** As:Sign address of new heap block to 'LineTable' . ************************,'


LineTable [Line] .LineAddress = Heappointer;
LineTable [Line] .LineLength = (unsigned char) (Column + 2) ;

} ,J* end InsertLine */

int ToinLine (SHORT Line)


/*
Combines the line in the file buffer given by 'Line' with the previous
line,
*/
(
/*** Re.turn if 'Line' is the first in the file (no previous line) . ***********/
if (Line -- 0)
return FALSE;

/*** Return if combined length would exceed maximum line length. *************/
if (LineTable [Line].LineLength + LineTable [Line -l].LineLength -2 >
LINEBUFS I Z )
return FALSE;

/*** Move existing characters in 'LineBuffer' to right to make room for the
characters from previous line. ******************************************/
me:nmove
(LineBuffer + LineTable [Line -1].LineLength - 2, /* Target
LineBuffer, /* Source
LineTable [Line].LineLength) ; /* Number of bytes

/*** Move the characters from previous line to beginning of 'LineBuffer' . ****/
movedata
(SELECTOROF (LineTable [Line -1].LineAddress) ,
OFFSETOF (LineTable [Line -1].LineAddress) ,
Lineselector ,
Lineoffset,
LineTable [Line -1] .LineLength -2) ;

/*** Adjust line length for added characters. ********************************/


LineTable [Line].LineLength += LineTable [Line -1].LineLength -2;

/*** Free block used by previous line. ***************************************/


if (WinFreeMem
(HHeap, /* Handle of heap from 'WincreateHeap'.
(BYTE NEAR *)OFFSETOF (LineTable [Line-1].LineAddress) , /* Offset.
LineTable [Line-1].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message,"managing heap; line %d", LINE_);
ErrorQuit (Message) ;
)

/*** Move all 'LineTable' members above and including 'Line' down one place. */
memmove
(&LineTable [Line -1], /* Destination. */
&LineTable [Line] , / * ScfAIrc:a. */

• Figure 6.2.4:
The source, code file for the example program (continued)
• 296 Programmer's Guide to the os/2PresentationManager

(LastLine -Line + 1) * sizeof (LineTable [0])); /* Bytes to move.*/


/*** Adjust 'LastLine'. ******************************************************/
--LastLine ;
return TRUE;

} /* end ToinLine */

void NewFile (void)


/*
Initializes the file buffer for a new empty file.
*/
(
PCH Farptr; /* Temporary far character pointer. */
/*** Initialize 'LineBuffer'. ************************************************/
LineBuffer [0] = '\n';
LineBuffer [1] = '\0';

/*** Initialize 'LineTable' for first (and only) line. ***********************/


LineTable [0] .LineAddress = MAKEP (Lineselector, Lineoffset) ;
LineTable [0] .LineLength = 2;

/*** Initialize 'LastLine'. **************************************************/


LastLine = 0;

/*** Create a heap to hold data added to file. *******************************/


HHeap = WincreateHeap
(0, /* Segment address: 0 means allocate new segment.
4096, /* Initial heap size.
0, /* Minimum increase size: 0 means use default.
0, /* Minimum # of dedicated free lists: none.
0, /* Maximum # of dedicated free lists: none.
HM MOVEABLE) ; /* Options: support movable objects.

/*** Obtain selector address of heap. ****************************************/


Farptr = WinLockHeap (HHeap) ;
Heapselector = SELECTOROF (Farptr) ;

} /* end NewFile */

int ReadFile /* Reads file into editor.


(char *FileName) /* Name of file.
(
FILE *PtrFile; /* File stream pointer.
long FileLength; /* Size of file.
USHORT Heapsize; /* Size of allocated heap.
NPCH Heapoffset; /* Offset of blocks within heap.
unsigned char LineLength /* Length of lines.
PCH Farptr; /* Temporary far pointer.
if ((PtrFile = fopen (FileName,"r")) == NULL) /* Open file.

• Figure 6.24..
The source code file for the example program (continued)
AdldingaKeyboardlnterface 297 .

return (ERROPEN) ;

/* Get length of file.


if ((FileLength = filelength (fileno (PtrFile))) == -1)
return (ERROPEN) ;

if (FileLength > 50000) /* Test file length.


return (ERRTOOBIG) ;

/* Make heap 20% larger than size of file.


Heapsize = (USHORT) (FileLength + FileLength / 5) ;

HHeap = WincreateHeap /* Allocate a heap.


(0, /* Segment address: 0 means allocate new segment.
Heapsize, /* Initial heap size.
/* Minimum increase size: 0 means use default.
/* Minimum # of dedicated free lists: none.
/* Maximum # of dedicated free lists: none.
/* Options: none.
Farptr = WinLocklleap (HHeap) ; /* Get far address of base of heap.
Heapselector = SELECTOROF (Farptr) ;/* Extract selector value.
LastLine = -1; /* Initialize index of last line.
while (fgets (LineBuffer,LINEBUFSIZ-1,PtrFile) != NULL)
(
if (++LastLine >= MAXLINES) /* Test limit of number of lines. */
return (ERRMAXLINES) ;

LineLength = (unsigned char)strlen (LineBuffer) + 1;/* Include null*/


if (LineLength == LINEBUFSIZ -1 && /* Insert '\n' into */
LineBuffer [LINEBUFSIZ -3] != '\n') /* overlength lines. */
(
LineBuffer [LINEBUFSIZ -2] = '\n';
LineBuffer [LINEBUFSIZ -1] = '\0';
++LineLength ;
)

Heapoffset = WinAllocMem /* Allocate block from heap.


(HHeap, /* Heap handle.
LineLength) ; /* Length of line to store.
if (Heapoffset == Nul,L) /* Test for error.
return (ERRALLOC) ;

/* Copy line into heap block. */


movedata (Lineselector, Lineoffset,Heapselector,
(unsigned) Heapoffset , LineLength) ;
/* Insert line information into the table.
LineTable [LastLine] .LineAddress = MAKEP (Heapselector,Heapoffset) ;
LineTable [LastLine] .Lir,eLength = LineLength;
)

• Figure 6.'.?.4o.
The source code file for the erample program (continued)
• 298 Programmer's Guide to the os/2 Presentation Manager

;'*** Place line 0 in working buffer. *****************************************/


GetTempBuf (0) ;

fclose (PtrFile) ; /* Close the file.


return (0) ;

) /* end of ReadFile */

void ReleaseTempBuf
(int Line) /* Number of line held in 'LineBuffer'. */
/*
This function:
o Allocates a new block of memory just large enough to hold the string in
the 'LineBuffer'
o Copies the string into the new block
o Adjusts the address in 'LineTable'
*/
(
NPCH Heapoffset; /* Offset of block within heap. */

/*** Allocate a block to hold current contents of 'LineBuffer' . **************/


Heapoffset = WinAllocMem
(HHeap,
LineTable [Line] .LineLength) ;
if (Heapof fset == NULL)
(
sprintf (Message,"out of heap memory; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

/*** Copy characters from 'LineBuffer' into new block in heap. ***************/
movedi::::::::::or, ;: :i:::::g::::::::::i:::x:u:::::r. :;
Heapselector, /* Target: selector of heap. */
(unsigned)Heapoffset, /* Target: offset of new block. */
LineTable [Line].LineLength) ; /* Bytes to copy. */

/*** Adjust address in 'LineTable' to point to new block. ********************/


LineTable [Line] .LineAddress = MAKEP (Heapselector, Heapoffset) ;

} /* end ReleaseTempBuf */

/*** Utility functions. ******************************************************/

void ErrorQuit /* Terminate program due to fatal error condition. */


(char *Message) /* Error message to display to user. */
(
char Buffer [60] ;
sprintf (Buffer,"Program Error: %s",Message) ;
WinMessageBox /* Display a message box.

• Figure 6.24..
The source code file for the example program (continued)
AddlingaKeyboardlnterface 299 .

(HWND DESKTOP, /* Handle of parent: desktop window.


1iFrame , /* Handle of owner: frame window.
Buffer, /* Message text.
"PM Text Editor", /* Caption.
0, /* Help window ID: not needed.
MB OK I /* Display an 'OK° button.
MB-ICONHAND) ; /* Display a hand icon.
Quit (1); /* Call normal termination function.
} /* end ErrorQuit */

void Quit
(.Lnt Errorcode) /* Process termination status.
Calls Presentation Manager termination functions and ends program
with specified error code.
/
iF (HHeap != NULL)
WinDestroyHeap (HHeap) ;
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue) ;
WinTerminate (HAncBlk) ;
exit (Errorcode) ;

) /* end Quit */

• Figure 6.24..
The source code file for the example program (continued)
J pter seven

tJsing Menus
and Accelerators
301.

his chapter incorporates a menu into the growing collec-

.T
tion of features for the Presentation Manager text editor.
Menus are a high-level facility offered by the Presenta-
tion Manager, and they are an important part of the uni-
form user interface. The example program uses a menu to implement
commands for managing files, for terminating the program, for locating
strings or specific line numbers, and for selecting program options.
Many of the menu commands can also be directly activated through
keystrokes that are termed keyboard ¢ccczcr¢fo7's.
Menus and keyboard accelerators are among the objects known as
Presentation Manager 7'cso#7'ccs. In this chapter, you will learn how to
design menus and designate accelerator keys using a resource script;
you will learn how to incorporate a menu into the standard window
collection and how to install accelerator keys; and you will learn how to
manage menus and accelerators by processing the messages these ob-
jects send to the client window. The chapter will also show you how to
implement the menu commands that do not require dialog boxes or
other features presented in later chapters. Specifically, the chapter
describes routines for saving the existing file, creating a new file, ter-
minating the program, displaying an About box (a program informa-
tion window), searching for a string, moving the cursor to a specific line
number, and toggling between insert and overwrite editor modes.
In this chapter, you win be introduced to two new buffer-management
functions and five new supporting uthity functions. The next complete
program hsting is Figure 8.38, which is given at the end of Chapter 8; this
hsting incorporates the features described in this chapter as wen as the
dialog boxes and dialog procedures presented in Chapter 8.

CREATING MENUS
• AND ACCELERATORS
Menus and accelerator keys are examples of Presentation Man-
ager resources. Resources are a special form of read-only data that are
stored directly in the executable program file on disk (the .EXE file), and
are read into memory when required at run-time. Resource data differ
• 302 Programmer's Guide to the os/2PresentationManager

from normal initialized program data. Normal initialized data (such as


strings and initialized external or static variables) are defined in the .C
source file and are placed by the linker into one or more data segments
in the .EXE file. Resource data, however, are not defined within the .C
source file; rather, they are inserted directly into the .EXE file ¢cr it has
been created by the linker. Resources are placed into special resource
segments (each resource, such as a menu or keyboard accelerator table,
is given a separate segment); these segments are not read until they are
actually required by the program at run-time. Also, since resource seg-
ments are marked as read-only, they can be shared by several instances
of the same program, and they may be discarded (and subsequently
reloaded) if additional memory space is required. (Note that resource
data can also be placed in dynamic-link library files, discussed in Chap-
ter 1, so that they can be shared by several different programs.)
Resources are prepared and inserted into the .EXE file by a utility
known as the 71csot/71cc co777p#cr. The general process for creating Presen-
tation Manager resources is illustrated in Figure 7.1. The first step is to
define the resources within a script file (with the extension .RC), which
is a normal ASCII file analogous to a .C source file. Using the resource
compiler, this file is then converted into a binary resource file (with the
.RES extension). The final step is to use the resource compiler once
again to insert the binary data from the .RES file directly into the .EXE
file. The manner in which a resource is loaded and used at run-time
depends upon the specific resource. This chapter describes the menu
and accelerator-key resources used by the example program; Chapter 8
describes the dialog boxes used by this program; and Chapter 10
describes icons, bitmaps, and other Presentation Manager resources.
Figure 7.2 hsts the resource script used to define the menu and ac-
celerator keys for the example program. Note that the script first includes
the header file OS2.H so that it can use the system constant identifiers. It
also includes the header file FIG7_3.H, hsted in Figure 7.3, which defines a
set of additional constants used to create and manage the menu and ac-
celerator table; this file must also be included in the .C source file so that it
can reference these same identifiers when managing the resources.
The menu definition, which follows the keyword MENU and the
identifier ID_FRAME RESOURCE, is enclosed between the words
BEGIN and END. The =onstant ID FRAME RESOURCE (defined in the
header file of Figure 7.3) will be-used to identify the menu resource
UsingMenusandAccelerators 303 .

OS2.H(SystemDefinitions)

APP.H(DefinitionsforF3esources)

inc ude incl ude

APP.C APP.PC
(C Source File) (Pesource Script Text File)

Icl/cAPP.C'

APP.OBJ(ObjectFile)
rc /r A PP.PC

IlinkAPP.OBJ'

APP.EXE APP.BES
(Without Pesources) (Binary Pesource Data)

rc APP.PES'

APP.EXE
(With Besources)

• Figure 7.1..
Creating Presentation Manager resources
• 304 Programmer's Guide to the os/2 PresentationManager

#include <OS2.H>
#include ''FIG7 3.H"

MENU ID FRAME RESOURCE


BEGIN
SUBMENU " ~File" , ID FILE
BEGIN
MENUITEM "~New", ID NEW
MENUITEM "~Open...\tF3", ID-OPEN
MENUITEM "~Save\t^S F2" ID-SAVE
MENUITEM ''Save ~As...", ID-SAVEAS
„-Print\t-P F4„, ID-PRINT
SEPARATOR
" -Exit" , ID EXIT
A-bout . . . " , ID-ABOUT
" -Edit" , ID EDIT
" Cu ~ t\tshi ft+Del " , ID CUT
" ~ Copy\tctrl+Ins" , ID_CoPY
" ~ Paste\tshi ft+Ins" ID-PASTE
" ~ Search" , ID SEARCH

" -Find . . . \t` F" ' ID FIND


''Find ~Next\t^N", ID-FINDNEXT
MENUITEM ''~Go to Line...\t^G", ID-GOTOLINE
END
SUBMENU " ~Options" , ID OPTIONS
BEGIN
MENUITEM ''Overwrite Mode\tlns", ID INSERT
END
„F1-Help" , ID HELP,
Mlg_HELP I MIS_BUTTONSEPARATOR

VK DELETE VIRTUALKEY , SHIFT


VK-INSERT VIRTUALKEY , CONTROL
vK_F2 , VIRTUALKEY
VK_F3 , VIRTUALKEY
VK F4' VIRTUALKEY
VK-INSERT VIRTUALKEY
VK-INSERT VIRTUALKEY , SHIFT
" ^F" ,
" `N" '
" ^ G" ,
" ^ p" '
"`s",
END

• Figure 7.2..
The resource script used to create a menu and define accelerator keys for the example program
UsingMenusandAccelerators 305 .

#def ine ID FRAME RESOURCE

#def ine ID FILE


#def ine ID-NEW
#def ine ID-OPEN
#def ine ID-SAVE
#def ine ID-SAVEAS
#def ine ID-PRINT
#def ine ID-EXIT
#def ine ID-ABOUT

#def ine ID EDIT


#def ine ID-CUT
#def ine ID-COPY
#def ine ID-PASTE

#def ine ID SEARCH


#def ine ID-FIND
#def ine ID-FINDNEXT
#def ine ID-GOTOLINE

#def ine ID OPTIONS


#def ine ID-INSERT

#def ine ID HELP

• Figure 7.3..
Constant definitions used for the menu and accelerator-key resources

when creating the standard window collection through the call to Win-
Createstdwindow. The menu definition contains two types of top-
level entries: those identified with the keyword MENUITEM and those
identified with SUBMENU. For each of these top-level items, the key-
word is followed by a string, which will appear permanently on the
horizontal menu bar at the top of the window, and an identifier, which
will be used by the program to manage the item. When the user selects
an item labeled with MENUITEM, the program immediately executes
the associated command; when, however, the user selects a SUBMENU
item, the system temporarily displays a pull-down submenu. An item is
selected either by clicking on it with the mouse, or by pressing the Enter
key while the item is highlighted.
The menu definition in Figure 7.2 contains the top-level items listed
in Table 7.1. The horizontal menu containing these top-level entries is
illustrated in Figure 7.4. Note that the submenus associated with each
top-level SUBMENU item are defined as nested lists of MENUITEM
entries; these entries are displayed in a temporary vertical pull-down
menu when the user selects the associated top-level item. When the
user subsequently selects a submenu item, the related command is im-
• 306 Programmer's Guide to the os/2 PresentationManager

keyword SEPARATOR generates a horizontal bar that separates menu


items. An example of a pull-down menu is shown in Figure 7.5.
Note that many of the menu strings contain a tilde (~). When the sys-
tem displays the menu, it underlines the character immediately follow-
ing the tilde (the tilde is not actually displayed), and allows the user to
select the associated item by simply typing this character. Many of these
strings also display the name of a keystroke following the menu item

• Table 7.1.. Tbp-level Menu Item_±__Def ined fortheExanpleprogra_in_

Keyword String Identifiers Style s


SUBMENU ``-File,,,
ID FILE
SUBMENU "-Edit„' ID EDIT
SUBMENI ``~Search'',
ID SEARCH
SUBMENI ``-Options„' ID OPTIONS
MENUITEM "F1=Help„, |D HELPz MI§-5:#P6N-

sEinRATOR

• Figure 7.4..
The top-level menu displayed by the example program
UsingMenusandAccelerators 307 .

label (for example, F2); these keystrokes are keyboard accelerators,


which cause immediate activation of the corresponding command
without requiring the user to go through the menu. (The symbol \t
generates a tab that vertically aligns the accelerator key names.)
The application program and the system use the constants, such as
ID_FILE and ID_NEW, to identify the specific submenus and menu
items. The manner in which the example program employs these iden-
tifiers is explained in the next section. You can select arbitrary values for
such identifiers; however, the identifier for each menu item should be
unique. (The constants used in the resource script of Figure 7.2 are
defined in Figure 7.3.)
Note that the definition of the last menu item (ID_HELP) contains an
additional field following the identifier. This optional field is used to
specify one or more menu styles or flags, which are combined with the
bitwise OR operator. The predefined identifier MIS_HELP (defined in
PMWIN.H) causes the item to generate a WM_HELP message rather
than a WM_COMMAND message (explained in the next section). The
identifier MIS_BUTTONSEPARATOR causes the system to separate the
item with a vertical bar and prevents the user from moving the high-
light to that item. The user can execute the help command from the key-
board by pressing the Fl key. (Pressing Fl automatically generates a
WM_HELP message; this key thus acts like a built-in accelerator.)

• Figure 7.5..
The pull-down menu displayed when the user selects the File submenu
• 308 Programmer's Guide to the os/2PresentationManager

The second part of Figure 7.2 defines the list of accelerator keys. This
resource is labeled with the keyword ACCELTABLE, followed by the
identifier ID_FRAME_RESOURCE; note that the identifier must be
the same as that used for the menu, since, as you will see, only a single
constant is passed to the Wincreatestdwindow function to identify
both resources.
The definition of each accelerator key consists of three main fields. The
first field identifies the keystroke by supplying either a virtual-key code or
a string containing thLe appropriate character. The virtual-key codes, such
as VK_DELETE for the Del key, are hsted in Table 6.1. The caret symbol (^)
preceding a character in a quoted keystroke indicates that the Ctrl key
must be pressed in conjunction with the character key; for example, ``^F"
represents the Ctrl-F keystroke.
The second field gives the identifier of the menu item that is to be ac-
tivated by the accelerator key. In other words, pressing the accelerator
key will generate a message containing this identifier exactly as if the
corresponding menu item had been selected; this process is explained
in the next section.
The third field specifies one or more options, separated by commas
(7tof combined with the bitwise OR operator). The VIRTUALKEY value
indicates that the first parameter contains a virtual-key code (otherwise,
the resource compiler will assume that the first parameter supplies a
quoted character). The SHIFT option specifies that the Shift key must be
down when the accelerator key is pressed, and the CONTROL option
similarly specifies that the Ctrl key must be pressed in conjunction with
the accelerator key. (You can likewise use the ALT option for the Alt key;
see the technical documentation for explanations of the other options.)
For example, the line

VK INSERT, ID COPY, VIRTUALKEY, CONTROL

defines the Ctrl-Ins keystroke as a keyboard accelerator that generates a


message containing the ID_COPY value; this is the same message sent
when the user selects the ID COPY item of the ID EDIT submenu.
Once you have prepared a resource script, which is contained in a file
with the .RC extension, the next step is to use the resource compiler to
convert this file into a binary format (contained in a .RES file) and then
insert the binary resource data directly into the .EXE file. The MAKE file
provided at the end of Chapter 8 (Figure 8.33) performs these steps
UsingMenusandAccelerators 309 .

using the following two commands:

rc /r FIG8 36.RC
rc FIG8 36.RES FIG8 38.EXE

The first command, which is executed only if the resource script has
been modified, converts the script file (FIG8_36.RC) into a binary
resource file (FIG8_36.RES). The second command is performed each
time a new .EXE file is prepared; this command inserts the binary data
from FIG8_36.RES directly into the executable file, FIG8_38.EXE. You
can perform both of these steps using the following single command:

rc FIG8 36.RC FIG8 38.EXE

The MAKE file of Figure 8.33, however, performs these steps separately
to avoid unnecessarily recompiling the resource script each time the
.EXE file is prepared. As you can see from the MAKE file, the script is
compiled only if the .RC file (or the header file it includes) has been
modified.
When the executable file is loaded, the resource segments are 7iof
automatically read into memory. Rather, the system reads a specific
resource segment only when the information is required. In the ex-
ample program, the resource data for the menu and accelerator table
are read when the standard window is created through the call to Win-
Createstdwindow. The latest version of the call to this function is listed
in Figure 7.6. Note that the second parameter (which specifies the frame
window styles) now includes the value FS_ACCELTABLE, which
causes the function to install an accelerator table. Also, the value as-
signed to the variable CtlData (the address of which is passed as the
third parameter) now includes the identifier FCF_MENU, which adds a
menu to the set of control windows included in the standard window.
The seventh parameter is set to 0, which indicates that the resources are
contained within the program .EXE file (if the resource segments are lo-
cated within a dynamic-link module, this parameter must contain the
module handle returned by the DosLoadModule OS/2 function).
Finally, the eighth parameter contains the resource ID for both the
menu and the accelerator (this is the ID assigned to these resources in
the script file, which must be the same for both resources).
• 310 Programmer's Guideto the os/2Presentation
Manager

ULONG CtlData = /* Control windows to include.


FCF HORZSCROLL /* Horizontal scroll bar.
FCF-MENI /* Menu.
FCF-MINmx /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-sysMEro /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR /* Title bar.
FCF-VERTSCROLL; /* Vertical scroll bar.

HFrame = Wincreatestdwindow /* Create parent window.


(HWND DESKTOP, /* Parent window handle.
FS_AC5ELTABLE I /* Install accelerator table.
WS VISIBLE, /* Frame window style.
&cEIData , /* Address of control data.
'mlN„ '
/* Client window class name.
Title, /* Text for title bar.
OL, /* Client window style.
0, /* Resource module handle.
ID FRAME RESOURCE, /* Resource identification.
&H5lientT; /* Address to receive client window hand.

• Figure 7.6..
The call to the function Wincreatestdwindow

Immediately after the call to Wincreatestdwindow, the function


main obtains the handle of the newly created menu window by calling
the function WinwindowFromlD, as follows:

menu = WinwindowFromlD /* Get handle of


/* menu window.
(HFrame, /* Handle of parent frame window.
FID RENU),. /* ID of menu child window.

The window menu handle stored in the global variable HMenu is used
later in the program. The function WinwindowFromlD is described in
Figure 4.5.
The resource data supply all the information the system needs to con-
struct the menu and accelerator table according to the specifications
supplied in the original resource script. The next section discusses the
messages sent when the user either selects a menu item or presses an
accelerator key.
Using Menus and Accelerators 311.

MANAGING MENUS
• AND ACCELERATORS
Onceyouhaveinstalledamenuandacceleratortablethroughthe
call to Wincreatestdwindow, the system displays the menu and al-
lows the user to access submenus and select menu items. The system
window procedure manages the menu, automatically performing such
tasks as displaying and removing pull-down submenus, and moving
the highlight from one menu item to another in response to the arrow
keys. The system sends messages to the client window whenever
relevant events occur. Your program, therefore, need only respond to
these messages and perform the requested commands.
The example program processes the following three general mes-
sages sent by the menu window procedure:

Message ID Cause of Message

WM INITMENU A submenu is first displayed.


WM COMRAND The user has selected a menu item or
pressed an accelerator key.
WM HELP The user clicked on the ID HELP
menu item or pressed the Fl key.

Accordingly, the main window procedure (Wndproc) of the current


version of the example program contains three additional branches in
the switch statement to handle these messages. Note that no special
processing is required to manage accelerator keys; the system automat-
ically translates these keystrokes into the appropriate messages.

The WM_INITMENU Message


The system sends the WM_INITMENU message (Figure 7.7)
whenever a menu item is about to become active. The example program
processes this message in the function InitMenu, listed in Figure 7.8.
This message gives the program an opportunity to perform any re-
quired initialization tasks immediately before a submenu is displayed.
The message supplies the identifier of the specific menu item in the
• 312 Programmer's Guide to the os/2Presentation
Manager

low-order word of mpl. InitMenu contains initialization routines for


the following three submenus:

Menu Identifier
(Low-order Word of mpl) Cause of Message

ID EDIT Edit pull-down submenu


is being displayed.
ID SEARCH Search pull-dour sub-
menu is being displayed.
ID OPTIONS Options pull-down sub-
menu is being displayed.

WM INITMENU
Purpose..
This message is sent by the system to the client window
when a menu item is about to become active.

Parameters..
REARAM mpl
low-order word: Identifier of the menu item becoming
active.
high-order word: 0.
REARAM mp2 Menu window handle.

Return Value ..
NULL.

Notes..
This message gives the client window procedure an oppor-
tunity to perform any necessary initializations before a sub-
menu is displayed.

• Figure7.7..
The WM_INITMENU Presentation Manager message
Using Menus and Accelerators 313.

MRESul,T EXPENTRY InitMenu (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

/*** 13ranch on the code for the specific submenu that is being displayed. ****/
switch (SHORTIFROMMP (mpl) )
(
case ID EDIT: /* 'Edit' submenu.

WinsendMsg /* Set attribute of 'Cut' menu item.


(HMenu' /* Handle of menu window.
MM SETITEMATTR, /* Set attribute of menu item.
MPFROM2 SHORT
( I D_CUT , /* 'Cut' menu item.
TRUE) , /* Include submenus.
MPFROM2 SHORT
(MIA DISABLED, /* Disabled attribute. . `
/* Disable only if block not marked. */
BlockMarked ? 0 : MIA DISABLED)) ;

WinsendMsg /* Set attribute of 'Copy' menu item.*/


(HMenu,
MM SETITEMATTR, /: g::d::t::b:::uo¥L::::. item. :/
MPFROM2SHORT
( I D_COPY ,
TRUE) ' /: i:::::em:::in::::: :/
MPFROM2SHORT
(MIA DISABLED, /* Disabled attribute. */
/* Disable only if block not marked. */
BlockMarked ? 0 : MIA DISABLED) ) ;

WinsendMsg /* Set attribute of 'Paste' menu item*/


( HMenu ,
MM SETITEMATTR, /: g::d::t::b:::uo¥±::::. item. :/
MPFROM2SHORT
( I D_PASTE ,
TRUE) , /: ::::::: ::::.:::T. :/
MPFROM2 SHORT
(MIA DISABLEDj /* Disabled attribute. */
/* Disable if no data in clipboard. */
ClipData ? 0 : MIA DISABLED) ) ;

return FALSE;
case ID SEARCH: /* 'Search' submenu. */
WinsendMsg /* Set attribute of 'Find Next' item.*/
(HMenu,
MM SETITEMATTR, /: g::d::t::b:::uo¥±::::. item. :/
MPFROM2 SHORT
(ID_FINDNEXT, /* 'Find Next' menu item.
TRUE) , /* Include submenus.
MPFROM2 SHORT
(MIA DISABLED, /* Disabled attribute.
/* Disable if no search string given.*/

• Figure7.8..
The function lnit:Menu of the example progran
• 314 Programmer'sGuidetothe os/2Presentation
Manager

Findstring [0] ? 0 : MIA DISABLED)) ;

return F`ALSE ;
case ID OPTIONS: /* Options submenu.

/* Set menu item text according to current insert status.


WinsendMsg
(menu, /* Menu handle.
MM_SETITEMTEXT, /* Set item text.
MPFROM2SHORT (ID_INSERT,0), /* ID of item.
Insert ? (MPARAM) (PCH)"Overwrite Mode\tlns" /* Text.
: (MPARAM) (PCH) ''Insert Mode\tlns") ;

return FALSE;
default :
return FALSE;

} /* end switch */
} /* end InitMenu */

• Figure7.8..
The function lritMeou of the example progran (continued)

Edit Submenu Initialization


As you can see from the resource script of Figure 7.2, the Edit sub-
menu contains three items: Cut, Copy, and Paste. These commands
manage the exchange of data between the program and the Presenta-
tion Manager clipboard, and are described in Chapter 9. The salient
point for the current discussion is that at a given time it may not be pos-
sible to execute one or more of these commands. Specifically, the pro-
gram cannot perform the Cut or Copy operation unless a block of data
is currently marked (the global program flag BlockMarked indicates
whether a block is marked). Also, it cannot execute the Paste operation
unless the Presentation Manager clipboard currently contains ap-
propriate data (indicated by the flag ClipData).
Accordingly, the initialization code d€.s¢bJes all menu items for com-
mands that cannot currently be executed, and c7i¢Z7Jes menu items for
those commands that can be executed. If an item is disabled, it is dis-
played in a halftone font and cannot be selected (if the user attempts to
select a disabled item, the menu will be removed as usual, but the sys-
tem will 77of send the command message to the client window).
UsingMenusandAccelerators 315 .

Menu items are enabled or disabled by sending the MM_SET-


ITEMATTR message (Figure 7.9) directly to the menu window. The
low-order word of the mpl parameter supplies the identifier of the
menu item (ID_CUT, ID_COPY, or ID_PASTE). The high-order word
contains a flag indicating whether submenus should be searched for the
specified item; this flag must be set to TRUE, since all three of these
menu items belong to submenus. The low-order word of the mp2
parameter is assigned the value MIA_DISABLED, which specifies that
the enabled status of the menu item is to be set. The high-order word is
assigned the value MIA_DISABLED if the menu item is to be disabled,
or the value 0 if the item is to be enabled. As you can see in the source
code, each menu item is either disabled or enabled depending upon the
current value of the appropriate variable: BlockMarked or ClipData.

Search Submenu Initialization


The Search submenu contains a Find item that allows the user to
enter a string (which is stored in the global buffer Findstring), and then
searches for the first occurrence of this string in the file beyond the cur-
sor position. The submenu also contains a Find Next item to locate the
next occurrence of the same string; if, however, Findstring does not
currently contain a string, this menu item should be disabled. Accord-
ingly, the Search submenu initialization routine sends a MM_SET-
ITEMATTR message-in the same manner as the Edit menu
routine-to either enable or disable this item, depending upon whether
the Findstring buffer is currently null.

Options Submenu Initialization


Finally, the InitMenu function contains a routine to initialize the
Options submenu. This submenu contains a single item (ID_INSERT),
which toggles the editor between insert and overwrite modes. When
the editor is in the insert mode, the submenu item should display the
string ``Overwrite Mode\tlns'', indicating that selecting the item will
change the program to the overwrite mode. Likewise, when the pro-
gram is in overwrite mode, the item should be labeled ``Insert
Mode\tlns''.
• 316 Programmer's Guide to the os/2 Presentation Manager

MM SETITEMATTR
Purpose..
This message is sent to a menu window to set the attributes
of a menu item.

Parameters..
REAEN mpl
low-order word: Identifier of the menu item (as
assigned in the resource script).
high-order word: A flag indicating. whether to search
submenus for an item with the
identifier given in the low-order word.
REAFEN mp2
low-order word: A mask for the attribute (s) you would
like to set; you can specify one or more
of the following values (combined
with the logical OR operator):

I dentifier Attrib ute


MIA CHECKED A check mark is
displayed next to the
menu item
MIA DISABLED The menu item is
disabled (if this
attribute is not selected,
the item is enabled)
MIA FRAMED A frame is drawn
around the menu item

high-order word: A mask for the new values to be


assigned to the bits specified by the
low-order word. You can specify one
or more of the same identifiers listed
for the low-order word.

• Figure 7.9..
The MM_SETITEMATTR Presentation Manager message
UsingMenusandAccelerators 317 .

Return Value ..
The menu window procedure returns TRUE if the service
has been successfully performed, and FALSE if an error
occurred.

Notes..
The original attributes of a menu item are specified in the
resource script; this message, however, can be used to
modify one or more attributes.
If the high-order word of mpl is set to TRUE and the menu
does not have an item with the specified identifier, the proce-
dure searches submenus for the matching item.
Note that each attribute is represented by a single bit in a
bit mask; the attribute is enabled if the corresponding bit is
on. The high-order word of mp2 is a bit mask specifying
which attributes you want to modify; the low-order word is
a bit mask indicating the actual desired value of each of these
attributes. For example, if you wanted to c7i¢Z7Jc the check
mark but dz.s¢Z7Zc the frame, you would assign the high-order
word of mp2 the value
MIA CHECKED I MIA FFLAMED

and the low-order word the value


MIA CHECRED

You can obtain the current state of an attribute for a given


item by sending the message MM_QUERYITEMATTR.

• Figure 7.9..
The MM_SETITEMATTR Presentation Manager message (continued)

Therefore, the initialization routine sets the text of this submenu item
according to the current value of the Insert flag. The text is set by send-
ing the MM_SETITEMTEXT message directly to the menu window.
This message is described in Figure 7.10.
®318 Programmer's Guide to the OS/2 Presentation Manager

MM SETITEMTEXT
Purpose..
This message is sent to a menu control window to specify the
text displayed for a given menu item.

Parameters..
REAEun mpl
low-order word: Identifier of the item (as assigned in
the resource script).
high-order word: 0.
REARAM mp2 Far pointer to a null-terminated string
containing the item text.

Return Value ..
The menu window procedure returns TRUE if the service
has been successfully performed, and FALSE if an error
occurred.

Notes..
The original text for the menu item is specified in the
resource script; this message, however, can be used to
change the item text.

• Figure 7.10..
The MM_SETITEM:TEXT Presentation Manager message

The WM_COMMAND Message


Thesystemnotifiesthechentwindowthattheuserhasselectedamenu
command by sending a WM_COMMAND message (Figure 7.11). The only
menuitemintheexampleprogramthatdcesnotgeneratethismessageisthe
Help entry OD_IHLP), which is disoussed in the next section.
WM_COMMAND is a general-purpose message sent by control win-
dows to their owners to signal significant events (in the case of a menu,
the owner is the frame window, which passes the message on to the
UsingMenusandAccelerators 319 .

WM COMMAND
Purpose..
This message is sent by a control window to its owner to
report a significant event.

Parameters..
REAEun "pl
low-order word: The command value.
high-order word: 0.
REJ- mp2
low-order word: Source of the message, which may be
one of the following values:

Identifier Message source


CMDSRC PUSH- Push-button control
BUTTON
CMDSRC MENU Menu control
CMDSRC ACCEL- Accelerator key
ERATOR
CMDSRC OTHER Other source

high-order word: If TRUE, the message was posted as


the result of a pointer device
operation; if FALSE, the message
resulted from a keyboard operation.

Return Value ..
NULL.

Notes..
See also a similar message, WM_CONTROL (Figure 8.18).

• Figure 7.1.1..
The WM_COMMAND Presentation Manager message
• 320 Programmer's Guide to the os/2 PresentationManager

client window). This message is accompanied by a value (in the low-


order word of mpl) that indicates the specific command. A menu con-
trol window sends this message whenever the user selects a menu item,
and passes the identifier of the selected item (which was specified in the
resource file) as the command value. The system also sends this mes-
sage-accompanied by the associated command value-when the user
presses an accelerator key.
.The example program processes WM COMMAND messages in the
function Command (portions of the fun-ction are listed in this section;
for a complete listing, see the source file in Figure 8.38, at the end of
Chapter 8). This function consists of a large switch statement, which
branches to the appropriate routine to process the selected menu item.
The menu item identifier (passed as the message command code) is
conveniently extracted using the COMMANDMSG macro, as follows:

switch (COMMANDMSG (&msg) ->cmd)

This use of this macro is exactly analogous to the use of the CHARMSG
macro, explained in Chapter 6 (in the section on The WM_CIIAR Message).
The menu selections listed in Table 7.2 are processed within the Com-
mand function.
Note that the descriptions of routines within this chapter are in the
section on The Menu Commands. As mentioned previously, not all
routines are described in the current chapter, since some of them require
dialog boxes or other features presented later in the book. The routines
described in Chapter 7 or 8 are implemented in the complete program
listing given in Figure 8.38; for routines that require techniques
presented in later chapters, this version of the program calls the func-
tion NotYet. The NotYet function simply displays a message box in-
dicating that a given routine has not yet been implemented (the name of
the nonimplemented routine is passed as a parameter). The function
NotYet is listed in Figure 7.12.

The WM_HELP Message


The last menu item defined in the resource script of Figure 7.2 is
labeled ``F1=HELP" and has the identifier ID HELP. Because this item
was defined with the MIS_HELP style, selecting it causes the system to
UsingMenusandAccelerators 321 .

send a WM_HELP message rather than a WM_COMMAND message.


Pressing the Fl key also generates a WM_HELP message. Note that you
need not install Fl as an accelerator key; it is automatically processed as
an accelerator key by the system.
The routine in the example program that handles the WM_HELP
message simply calls the NotYet function to notify the user that the help
facility has not yet been implemented. Implementing a help utility is
not covered in this book, but rather is left as a project for the reader.

• Tabl,e 7.2.. Menu Selections Processed within the Co"rr\aLnd Function

ID Menu Item Description


ID NEW New (File submenu) Chapter 7
ID OPEN Open (File submenu) Chapter 8
ID SAVE Save (File submenu) Chapter 7
ID SAVEAS Save As (File submenu) Chapter 8
ID PRINT Print (File submenu) Chapter 12
ID EXIT Exit (File submenu) Chapter 7
ID ABOUT About (File submenu) Chapter 8
ID CUT Cut (Edit submenu) Chapter 9
ID COPY Copy (Edit submenu) Chapter 9
ID PASTE Paste (Edit submenu) Chapter 9
ID FIND Find (Search submenu) Chapter 8
ID FINDNEXT Find Next (Search sub- Chapter 8
menu)
ID GOTOLINE Go to Line (Search sub- Chapter 8
menu)
ID INSERT Overwrite Mode/ Insert Chapter 7
Mode
(Options submenu)
• 322 Programmer's Guide to the os/2 Presentation Manager

void NotYet (char *Message)


(
char Buffer [60] ;

/* Format message.
sprintf (Buffer,"Not Yet Implemented: %s",Message) ;
WinMessageBox /* Display a message box.
(HIND DESKTOP, /* Handle of parent -- try frame.
HFrame , /* Handle of owner.
Buffer, /* Message text.
''PM Text Editor", /* Caption.
0' /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB ICONASTERISK) ; /* Display an asterisk.
} /* end NotYet */

• Figure 7.12..
The function NotYct of the example program

• THEMENUCOMMANDS
This section describes the routines for executing the menu com-
mands that do not require dialog boxes or other features treated in sub-
sequent chapters. Each of these routines is contained in a branch of the
switch statement, within the function Command.

The New Command


The routine for the New command of the File submenu is listed in
Figure 7.13. This routine is executed whenever the WM_COMMAND
message has a command value of ID_NEW, the identifier assigned to
the New menu item within the resource script. The New command
clears the current contents of the file buffer and reinitializes the buffer
for a new, empty file that is initially unnamed.
The routine first checks the Modified variable to determine whether
the file buffer contains modified data that has not been saved to disk.
This global variable is defined in the program as follows:

unsigned char Modified = 0,.


UsingMenusandAccelerators 323 .

Modified is initialized to 0 whenever a file is first read or saved to disk,


and it is set to 1 whenever the user modifies the file data contained
in the buffer. (Note that the Character function and the Del-key and
F9-key routines of the VirtKey function now set this flag to 1 before
altering the file buffer; you will see how it is processed by the file-
management routines.)
If the buffer has been modified, the routine warns the user by dis-
playing a message box through a call to WinMessageBox (Figure 3.14).
The message box displays a string asking the user whether the current
file should be saved, and it contains a Yes button and a No button; Win-
MessageBox returns a code indicating which of these buttons the user

case ]:D NEW: /* 'New' file menu item.


if (Modified) /* File is modified.
(
/* Warn user and elicit response on saving file.
Reply = WinMessageBox
(HWND DESKTOP,
hwnd ,
''File Unsaved; Save?",
''PM Text Editor",
0'
MB_YESNO I
MB ICONQUESTION) ;

/* If reply is Yes, send a 'Save' message to client.


if (Reply == MBID YES)

/* Repeat message until file successfully saved.


while (Modif led)
WinsendMsg
( hwnd ,
wM cormND,
MPFROM2SHORT (ID SAVE, 0) ,
OL);

} /* end if Modified */
ReleaseFile () ; /* Free current heap.
NewFile (); /* Initialize a new file.
FileName [0] = '\0'; /* New file is untitled.
ShowFileName () ; /* Display ''Untitled" in title bar.
::::::::o: % , ,: 3::e:nT:::fi::n:::7;ursor values.
return FALSE;

• Figure 7.13..
The routine for the New command of the File submenu
• 324 Programmer's Guide to the os/2 PresentationManager

selected. If the user chooses to save the file, the program then sends a
WM_COMMAND message (with an ID_SAVE command code) back to
the client window. This recursive message activates the Save routine,
described later in the chapter, exactly as if the user had selected this
item from the File submenu.
The routine now performs a series of steps to reinitialize the file buff-
er and the data displayed within the window for a new, empty, and un-
named file. First, it calls the function ReleaseFile (Figure 7.14), which is
in the buffer-management module and serves to release the current file
data by destroying the Presentation Manager heap that had been allo-
cated when the file was first created or read from the disk. It then calls
the function NewFile, described in Chapter 6, to initialize a new, empty
file within the file buffer.
The routine next assigns the value NULL to the first character of the
string FileName. FileName is a global string that contains the fully
qualified name of the current file (that is, the file name including the
drive and full directory path specifications). Whenever the file is cur-
rently unnamed, the first character of this string is set to NULL.
In the present version of the example program, the function main as-
signs an initial value to FileName. If the user has not entered a file name
on the command line, it sets the first character of FileName to NULL to
indicate an unnamed file. If, however, the user included a file name on
the command line, main assigns the fully qualified version of this name
to FileName. The fully qualified path name corresponding to a given

void ReleaseFile (void)


Destroys the current heap, thereby freeing all file data.
(
if (HHeap != NULL)
WinDestroyHeap (HHeap) ;

return ;
} /* end ReleaseFile */

• Figure 7.14:
The ReleaLseErle function of the example program
UsingMenusandAccelerators 325 .

file is obtained through the function Qualify, which is called from func-
tion main as follows:

Qualify (argv [1] , FileName) ,.

Qualify is a utility function contained within the example program and


is listed in Figure 7.15.
Qualify accepts a file name (given by the first parameter) and con-
verts this name+if necessary-to a fully qualified name, which is writ-
ten to the string specified by the second parameter. If the input name

void Qualify (char *Unqual, char *Qual)


/*
Converts file name 'Unqual' (either a simple or qualified file name) to
a fully qualified file name, which includes the drive specification and
full directory path, and is copied to 'Qual' .
*/
(
char PathBuffer [PATHLENGTH] ;
chaLr *Ptrpath = PathBuffer;
Getpath (PathBuffer, sizeof (PathBuffer) ) ;
if (*.(Unqual + 1) == I:')
(
*Qual++ = *Unqual++;
*Qual++ = *Unqual++;
Ptrpath +-2;
)
else
(
*Qual++ = *Ptrpath++;
*Qual++ = *Ptrpath++;
)
if (*Unqual !-'\\')
(
while (*Qual++ = *Ptrpath++)
if (*(Qual -2) --'\\')
--Qual ;
else
*(Qual -1) -'\\';
)

while (*Qual++ = *Unqual++)

} /* end Qualify */

• Figure 7.1.5:
The Qual.lfy function of the example program
• 326 Programmer's Guide to the os/2PresentationManager

already contains a full drive and path specification, it is simply copied


to the output name. If the input name lacks a drive specification, the
function adds the current default drive to the output name; and if
the input name lacks a full directory path (which must begin from the
root directory), the function adds the current directory path to the out-
put name. (Note that under OS/2, the system maintains a separate
default drive and directory for each process.)
Qualify obtains the current disk drive and directory path by calling
another utility function, Getpath (listed in Figure 7.16). Getpath calls
two OS/2 kernel functions; it obtains the current drive through Dos-
QCurDisk and the current directory path through DosQCurDir.
Note that the program must save the fully qualified file name be-
cause, as you will see in Chapter 8, the user can change the current drive
or directory at any time through the Open menu command. If the

void Getpath (char *Path, int Pathsize)


Copies fully qualified path to 'Path' ; will not copy beyond the length of
'Path' given by Pathsize.

tsHORT DriveNumber; /* Disk drive number. */


ULONG LogicalDrives; /* Mapping of installed drives. */

/* If target buffer is too small, return without altering it. */


if (Pathsize < 3)
return ;
/* Obtain current default disk and mapping of installed drives.
DosQCurDisk

i::=±¥:I::::=:, ; ,: E:::±¥:: ::g;T;::go:fc¥:::::I::±¥:;ves.


/* Write drive letter to 'Path' .
sprintf (Path,"%c:\\",DriveNumber + 64) ;

/* Adjust 'Pathsize' for drive specification.


Pathsize -= 3;

/* Obtain current default directory.


DosQCurDir
( Dr iveNumber , /* Drive number: current drive.
Path + 3, /* Address of buffer to receive directory.
&pathsize) ; /* Length of buffer to receive directory.
return ;
} /* end Getpath */

• Figure 7.16..
The GetpaLth utility function of the example program
UsingMenusandAccelerators 327 .

program did not store the drive and directory associated with the cur-
rent file, this file could easily be written to the wrong directory when it
is saved.
Once FileName has been set to an empty string indicating an un-
named file, the routine for the New command calls the ShowFileName
utility function (listed in Figure 7.17) to update the file name displayed
in the window title bar. The present version of the example program
displays the name of the current file along with the name of the pro-
gram within the title bar. The function main specifies an empty title (``'')
in the call to Wincreatestdwindow and then immediately calls Show-
FileName to set the appropriate title. The function ShowFileName sets
the title text by calling the Presentation Manager function Winset-
WindowText, which is described in Figure 7.18. Before setting the title
bar, the function ShowFileName formats the title bar text using the fol-
lowing command:

sprintf (Title, "PM Editor -%s", FileName[0]


? Unqualify (FileName) : " (Untitled) ") ,.

The file name written to the title bar text (Title) by this command is
either the current file name, or the string ``(Untitled)" if FileName is
empty. Note, however, that rather than displaying the fully qualified
file name, the program obtains the simple file name by calling the utility
function Unqualify (listed in Figure 7.19).

void Sh()wFileName (void)


/*
Upclates the text in the title bar to show the current file name.
*/
(
/* Format title.
spl.int£ (Title, ''PM Editor -%s", FileName[0] ? Unqualify (FileName)
: „(Untitled)„);

/* Modify the title bar window text.


Wir..SetwindowText
(HFrame, /* Window handle: frame routes text to menu.
Title) ,. /* String containing the text.
} /* end ShowFileName */

• Figure 7.1-/'..
The ShowHLltENarne function of the example program
• 328 Programmer's Guide to the os/2PresentationManager

Unqualify locates the simple file name (that is, the name and exten-
sion without the drive or directory specifications) within the string con-
taining a fully qualified name that is passed as a parameter. It then
converts the simple name to uppercase letters, and returns a pointer to
the portion of the string containing this name. The characters of the
simple name are converted to uppercase using the Presentation
Manager function Winupper, which is described in Figure 7.20. Thus,
all file names displayed in the title bar are simple names in uppercase
letters, in conformance with the Presentation Manager style guidelines.

WinsetwindowText
Purpose..
Sets the text associated with a window.

Prototype..
BOOL APIENTRY WinsetwindowText
(HWND hwnd, Handle of the window.
psz pszText) ,. A nun-terminated string containing the text
to be assigned to the window given by hwnd.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
The manner in which the text passed to this function is used
depends upon the specific target window. If hwnd is the frame
window handle, the specified text is displayed in the title bar
control window.

Relate d Function..
WinQuerywindowText (Figure 8.16)

• Figure 7.18..
The W±nsetwindowText Presentation Manager f unction
UsingMenusandAccelerators 329 .

Finally, after resetting the Modified flag to 0, the New file routine
calls the utility function Initwindow to initialize the window for a
new file. This function is listed in Figure 7.21, and performs the follow-
ing tasks:

• It sets the global variables cursorcol and cursorLine to o so that


the cursor is associated with the first character of the new file.
• It sets TopLine and Firstcol to o so that the beginning of the file
is displayed in the window.
• It adjusts TopLineMax and FirstcolMax to reflect the current
size of the file and dimensions of the window.
• It adjusts the positions and ranges of the vertical and horizontal
scroll bars.
• It positions the cursor at the upperleft corner of the window.
• It invalidates the entire window to force the paint function to dis-
play the new file data.

char *Unqualify (char *Qual)


Returns a pointer to the simple file name within the string 'Qual' ,
which contains a partially or fully specified file path. Converts the
unqualified file name to upper case.
*/
(
char *Ptrch;
P1:rch = Qual + strlen (Qual) ;

while (Ptrch
* ( Ptrch-1 )
* ( Ptrch-1 )
--Ptrch ;
wj'Lnupper /* Convert unqualified name to upper case.*/
(HAncBlk, /* Anchor block handle. */
NULL, /* Code page: use current. */
NULL, /* Country code: use default. */
Ptrch) ; /* Address of string to be converted. */
return (Ptrch) ;
} /it end Unqualify */

• Figure 7.19..
The Unqudify function of the example program
• 330 Programmer's Guide to the os/2 Presentation Manager

Winupper
Purpose..
Converts the characters in a string to uppercase.

Prototype..
SHORT APIENTRY Winupper
(HAB hab, Anchor block handle.
USHORT idcp, Code page to use; a NULL value causes the
function to use the code page for the current
process.
USHORT idcc, Country code; a NULL value causes the
function to use the default country specified
in the CONFIG.SYS file.
psz psz) ,. Pointer to the string to be converted.

Return Value ..
The length of the converted string.

Notes..
The function directly modifies the characters in the string
passed through the parameter psz (that is, the string is
modified in place).

• Figure 7.20..
The WLnupper Presentation Manager function

The Save Command


The routine for the Save command of the File submenu is listed in
Figure 7.22. This routine is executed in response to a WM_COMMAND
message with an ID_SAVE command code, which is generated when-
ever the user selects the Save menu item or presses the Ctrl-S accelerator
keystroke. If the current file has been named (that is, FileName is not
UsingMenusandAccelerators 331 .

void -[nitwindow (void)


/* 'rhis function initializes the window when a new file is read ('Open'
File menu item) , or when a new empty file is started ('New' file menu
itiem). It performs the following tasks:_
o Initializes global cursor and window variables so that the cursor
is placed at the first character of the file, and the beginning of
the file is displayed in the window.
o Adjusts range and position of horizontal and vertical scroll bars.
o Positions the cursor at top left of window.
o Invalidates the entire window to force displaying the new data.
*/
(
Cursorcol = CursorLine = 0;
TopLine = Firstcol = 0;
'ropLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
:FirstcolMax = LINEBUFSIZ - 2 - xwin / xchar;
WinsendMsg /* Adjust range/position of slider.
(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPF50M2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable scroll bar if scrolling is possible. *


(HVscroll, /* Recipient handle (vertical scroll bar).*
TopLineMax ? TRUE : FALSE) ; /* Enable only if max.

WinsendMsg /* Adjust range/position of slider.


(HHScroll, /* Recipient handle: horizontal scroll
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (Firstcol, 0) , /* Position.
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range.

if (Hclient == WinQueryFocus (HWND DESKTOP,FALSE) )


Wincreatecursor /* SEt cursor position.
(Hclient'
(Cursorcol - Firstcol) * xchar,
ywin - (CursorLine - TopLine + 1) * ycharTot,
0'
0'
CURSOR SETPOS ,
NULL) ;

WinlnvalidateRect /* Invalidate entire window.


(Hclient' /* Client window handle.
0' /* Rectangle: 0 means whole window.
FALSE) ; /* Do not automatically include children.
} /* end Initwindow */

• Figure 7.21..
The function lr\i+Window of the example progran
• 332 Programmer's Guide to the os/2PresentationManager

empty), the routine saves the file under this name and returns; if, how-
ever, the file is unnamed, the Save routine drops fferottgfe to the Save As
routine (described in Chapter 8), which obtains a file name from the
user before saving the file.
The file is saved by calling the SaveFile function of the buffer-
management module (listed in Figure 7.22), which is passed the fully
qualified file name. SaveFile is similar to ReadFile (described in Chap-
ter 3); it opens and closes the file using the high-level C functions fopen
and fclose, and writes each file line using the fputs function. See the
section on enhancements, at the end of the chapter, for several sugges-
tions on improving this routine.

int SaveFile (char *FileName)


(
register int i; /* Loop counter.
FILE *PtrFile; /* File stream pointer.
char TempBuffer [LINEBUFSIZ] ; /* Temporary local buffer for lines.
PCH Farptr; /* Temporary far pointer.
unsigned Bufsel; /* Selector of 'TempBuf ' .
if ((PtrFile = fopen (FileName,"w")) == NULL) /* Open file.
return FALSE;
Farptr = (char far *)TempBuffer; /* Obtain selector for 'TempBuf'.
Bufsel = SELECTOROF (Farptr) ;

/* Write f.ile line by line.


for (i = 0; i <= LastLine; ++i)
(
/* First copy line into a local buffer.
movedata /* Block copy.
(SELECTOROF (LineTable [i].LineAddress) /* Source selector.
OFFSETOF (LineTable [i].LineAddress) , /* Source offset.
Bufsel , /* Target selector.
(unsigned int) TempBuffer, /* Target offset.
LineTable [i] .LineLength) ; /* Length of line.
/* Write line to file.
fputs (TempBuffer, PtrFile) ;
)

fclose (PtrFile) ; /* Close file.


return TRUE;

} /* end SaveFile */

• Figure 7.22..
The SaveEIle function of the example program
UsingMenusandAccelerators 333 .

If SaveFile encounters an error, it returns FALSE, and the calling


routine displays a message box to notify the user that the file cannot be
saved. After the user has dismissed the message box by selecting the Ok
button, the Save routine immediately returns. Therefore, the user must
reissue the menu command to make another attempt to save the file. If
SaveFile is successful, it returns TRUE, and the calling routine resets
the Modified flag to 0 and returns.
Note that the Save routine is also invoked through messages sent by
the New routine of the Command function (described earlier in the
chapter), and by the Quit function. The current version of the Quit
function checks the Modified flag before terminating the program. If
the file buffer contains unsaved data, the function displays a message
box and sends an ID_SAVE message if the user chooses to save the file.
The code for performing these steps is the same as that in the New
routine, listed and described in the previous section.

The Exit Command


When the user selects the Exit item of the File submenu, the sys-
tem sends a WM_COMMAND message with the ID_EXIT command
code. The routine that processes this message terminates the program
by calling the Quit function. Note that this menu item provides an alter-
native to the Close item on the system menu (which generates a
WM_QUIT message that terminates the message-processing loop in the
function main).

The Insert/Overwrite Mode Command


When the user selects the Insert item of the Options submenu or
presses the Ins accelerator key, the system generates a WM_COM-
MAND message with the ID_INSERT code. (Note that this item is
labeled either ``Overwrite Mode" or "Insert Mode," depending upon
the current state of the Insert flag.) The routine that handles this mes-
sage simply toggles the current state of the Insert flag, as follows:

Insert ^= 1,.
• 334 Programmer's Guide to the os/2 Presentation Manager

Note that this statement was formerly located in the VK_INSERT


branch of the VirtKey function (which processes WM_CHAR messages
that have valid virtual-key codes). However, because the Ins key is cur-
rently defined as an accelerator, it causes the system to generate a
WM_COMMAND message rather than a WM_CHAR message.

• ENHANCEMENTS
This section offers two suggestions for improving the file-saving
routine, SaveFile, described earlier in this chapter.
When SaveFile writes a file, it simply overwrites the previous version
ofthisfileonthedisk.Thefirstenhancementwouldbetomodifythisfunc-
tion so that it maintains a backup copy of the prior version of the file that is
being saved. For example, if the file is named MEMO.TXT, you could
maintain a backup copy through the fouowing steps:

1. If the file MEMO.BAK exists in the same directory where the file
is being saved, it should be deleted (you can use the C function
unlink or remove, or the OS/2 service DosDelete).
2. If the file MEMO.TXT exists in the same directory where the file
is being saved, it should be renamed to MEMO.BAK (you can
use the C function rename, or the OS/2 service DosMove).
3. Write the current contents of the buffer to a new file named
MEMO.TXT.

A second possible enhancement would be to write the data to the file


using the basic OS/2 services Dosopen, Doswrite, and Dosclose. The
current version of SaveFile uses the C functions fopen, fputs, and
fclose for the sake of simplicity and to maintain consistency with the
function ReadFile. The problem with the C function fputs, however, is
that in the small data memory model used by the example program, the
string address passed as the first parameter is a 7icczr pointer (that is, it
contains ordy the address offset), and the function assumes that the
string resides in the automatic data segment. The data in the heap, how-
ever, are located in a separate segment and must be addressed with /czr
UsingMenusandAccelerators 335 .

pointers. Accordingly, SaveFile must copy each file line into a local
buffer before writing the line with fputs.
Because the OS/2 function Doswrite accepts a far pointer to the
source buffer, you can write the data directly from the heap to the file
without an intermediate copy operation. Note, however, that you will
have to insert a carriage-return character (ASCII 13) at the end of each
line, since the lines stored in the heap contain only a newline character
('\n', or ASCII 10). (C functions such as fputs automatically translate
the newline character to a newline/carriage-return pair if the file was
opened in text mode.)

• CONCLUSION
The next, and final, complete listing of the example program is
provide in Figure 8.38, at the end of Chapter 8, together with a MAKE
file and the required definition, resource, and header files.
This chapter has added a complete menu and set of accelerator keys
to the example program, and several of the menu commands have been
fully implemented. For many of these commands, however, the pro-
gram must provide additional information to the user and solicit the
user's responses. For example, the Open command of the File submenu
should display a list of files on the disk and allow the user to enter a file
name. Such interaction with the user is easily accomplished through the
medium of dialog boxes, which are the topic of the next chapter.
hapter eight

Designing
Dialog Boxes
337.

any of the commands listed in the Presentation Manager


menu presented in the previous chapter require addi-

.tw tional interaction with the user. The text for each of these
commands is followed by an ellipsis (...), indicating that
the program must ehcit further information before it can execute the
command. This information is obtained through the dialog boxes de-
scribed in this chapter. A dialog box is a window managed by a system
procedure that contains an organized collection of child control win-
dows, such as text strings, edit fields, and push buttons; the child control
windows are used to display data and obtain information from the user.
The dialog boxes employed by the example program are displayed
when the user selects the related menu item, and they are removed when
the user dismisses them.
In this chapter, you will learn how to design a dialog box using the
Dialog Box Editor; you will learn how to display a dialog box from
the client window procedure; and you will learn how to write a proce-
dure to process the messages that are sent to a dialog box. The complete
listing of the current version of the example program is given in Figure
8.38, at the end of the chapter, accompanied by the other files needed to
build the executable program.

• CREATINGADIALOGBOX
This section describes how to design a dialog box and how to dis-
play a dialog box from the client window procedure; the next main sec-
tion discusses how to manage a dialog box once it has already been
displayed.
When you request the system to display a dialog box, you must
supply a fc77zpJ¢£c, which is a collection of data describing the dimen-
sions and styles of the dialog box and all the child control windows that
it contains. You can furnish these data in the form of a Presentation
Manager resource, in the same manner that you supply the data re-
quired to create menus and accelerator tables. As described in the pre-
vious chapter, the first step in creating resource data is to define these
data in a resource script, which is then translated into binary format
and inserted into the executable file using the resource compiler.
• 338 Programmer's Guide to the os/2 PresentationManager

The resource script used to create the dialog boxes for the example
program is listed in Figure 8.1. Just as a menu is defined following the
keyword MENU and an accelerator table definition follows the keyword
ACCELTABLE, each dialog template definition is labeled with the
keyword DLGTEMPLATE. Note that you must define a separate
resource for each dialog box; as you can see in Figure 8.1, the resource
script defines five dialog boxes.
Fortunately, you never have to create a resource script such as the one
in Figure 8.1. Rather, you can generate the script file using the Dialog
Box Editor. The Dialog Box Editor is a Presentation Manager program
that allows you to interactively create one or more dialog boxes; once
you have designed the dialog boxes, you can use this utility to automat-
ically generate a resource script that you can subsequently process with
the resource compiler (the script in Figure 8.1 was generated by the
Dialog Box Editor).
Each of the dialog templates in Figure 8.1 contains a large and con-
fusing collection of fields that specify the dimensions, locations, iden-
tifiers, and attributes for both the dialog box and its child control
windows. Using the Dialog Box Editor, however, you can easily select
all dialog box objects and their attributes directly from program menus.
Also, you can specify dimensions and locations by directly moving and
resizing objects on the screen using the mouse, rather than by supplying
numeric values. Accordingly, instead of describing the individual fields
and identifiers of the script file, this section explains how to create a
dialog box template through the Dialog Box Editor. Following a general
description of using this utility, the section illustrates each of the dialog
boxes employed by the example program and lists the options that were
selected from the Dialog Box Editor to create these dialog boxes.

Using the Dialog Box Editor


The Dialog Box Editor, DLGBOX.EXE, is a Presentation Manager
application that provides a menu, dialog boxes, a mouse interface, and
a context-sensitive help facility. The window display that you see when
you first start this utility is illustrated in Figure 8.2.
The following are the general steps for using the Dialog Box Editor to
design one or more dialog boxes, and to generate the corresponding
DesigningDialogBoxes 339 .

/*
Figure 8.1

Dialog box resource script generated by the Dialog Box Editor.


*/

DLGTEMI'IjATE 257 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "I, 257, 69, 37, 180, 74, FS_NOBYTEALIGN I FS_DLGBORDER I
WS CLIPSIBLINGS I WS_SAVEBITS
BEGIN
CONTROL ''Save File As:", -1, 3, 50, 63, 8, WC STATIC,
SS TEXT I DT_LEFT I DT_TOP I WS_GROUP| WS_VISIBLE
CONTROL ""T 257, 5, 31, 170, 13, WC_ENTRYFIELD, ES_LEFT I ES_AUTOSCROLlj
ES MARGIN I WS_TABSTOP I WS_VISIBLE
CONTROL "CIrrent Directory:", 258, 3, 61,174,11, WC_STATIC, SS_TEXT I
DT LEFT I DT_TOP I WS_GROUP I WS_VISIBLE
CONTROL "E=c=Cancel", 2, 99, 7, 56,16, WC BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CONTROL "Save", 1, 25, 8, 53, 14, WC BUTTON, BS_PUSHBUTTON I BS_DEFAULT
WS TABSTOP I WS_VISIBLE
EN[)
END

DLGTEMI'IjATE 258 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "", 258, 71, 43, 182, 53, FS NOBYTEALIGN I FS_DLGB0RDER I
WS CLIPSIBLINGS I WS_SAVEBITS
BEGIN
CONTROL "", 258, 37, 35, 141, 10, WC ENTRYFIELD, ES_LEFT I
ES AUTOSCROLL I ES_MARGIN I ffs_TABSTOP I WS_VISIBLE
CONTROL "E=c=Cancel", 2, 105, 9, 60, 13, WC BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CONTROL "Flnd", 1, 21, 9, 53, 13, WC BUTTON, BS PUSHBUTTON I BS_DEFAULT
WS TABSTOP I WS_VISIBLE
CONTROL "Flnd:", -1, 6, 35, 23, 9, WC STATIC, SS_TEXT I DT_LEFT I
DT TOP I WS_GROUP I WS_VISIBLE
EN[)
END

DLGTEMI'IiATE 259 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "', 259, 90, 51, 147, 52, FS NOBYTEALIGN I FS_DLGBORDER I
WS CLIPSIBLINGS I WS_SAVEBITS
BEGIN
CONTROL "Go to Line Number:", -1, 3, 33, 86, 10, WC STATIC,
SS TEXT I DT_LEFT I DT_TOP I WS_GROUP I WS_VISIBLE
CONTROL ""T 259, 96, 35, 45, 7, WC ENTRYFIELD, ES_LEFT I ES_AUTOSCROLL
ES MARGIN I WS_TABSTOP I Wg_VISIBLE
CONTROL "E=c=Cancel", 2, 77, 11, 61, 14, WC BUTTON, BS PUSHBUTTON I
WS VISIBLE
CONTROL "G6 to Line", 1, 9, 12, 52, 12, WC BUTTON, BS PUSHBUTTON I
BS DEFAULT I WS_TABSTOP I WS_VISIBLE
ENI)

• Figure 8.1:
Resource script defining the dialog templates for the example program
•340 Programmer's Guide to the OS/2 Presentation Manager

END

DLGTEMPIIATE 260 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG MM, 260, 74, 17, 153, 123, Fs_NOB¥TEALIGN I Fs_DmBORDER I
WS_CLIPSIBLINGS I WS SAVEBITS
BEGIN
CONTROL "Open File Name:", -1, 3,108, 78,10, WC STATIC,
SS TEXT I DT_LEFT I DT_TOP I WS_GROUP I W5 VISIBLE
CONTROL ""T 260, 5, 93, 132, 11, WC_ENTRYFIELD, ES=LEFT I ES_AUTOSCROLL
ES_MARGIN I WS_TABSTOP I WS VISIBLE
CONTROL "", 261, 3, 67,137, 8, WC_STATIC, SS_TEXT I DT_LEFT I
DT_TOP I WS_GROUP I WS VISIBLE
CONTROL "", 262, 5, 6, 82, 57,-WC_LISTBOX, WS_TABSTOP I WS VISIBLE
CONTROL "Open", 1, 95, 41, 57, 13, WC_BUTTON, BS_PUSHBUTTOIf I BS DEFAULT
WS TABSTOP I WS VISIBLE
CONTROL "E=c=Cancel", 2T 93,12, 59,16, WC_BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CONTROL "CIrrent Directory:", -1, 3, 79, 76, 9, WC_STATIC, SS_TEXT I
DT_LEFT I DT TOP I WS_GROUP I WS VISIBLE

END

DLGTEMPIIATE 256 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "", 256, 108, 32,114, 85, FS_NOBYTEALIGN I FS_DLGBORDER I
WS_CLIPSIBLINGS I WS SAVEBITS
BEGIN
CONTROL "Presentation Manager", -1, 2, 67,110, 9, WC STATIC,
SS TEXT I DT CENTER I DT_TOP I WS GROUP I WS VISIBLE
CONTROL ;:===NES±tTr;i_=5± i,w§46R533, , 9*swsf§:3:=c, ss TEXT ,

CONTROL ''Version 1.0", -1, 3, 46,109, 9, tic_STATIC, SS TEXT I


DT_CENTER I DT_TOP I WS_GROUP I WS VISIBLE
CONTROL #S=:io:i i9*sL:A83±6pli,wgcv:g:::¥T BS_PUSHBUTTON I BS DEFAULT I

• Figure 8.1..
Resource script defining the dialog templates for the exanple program (continued)

resource script (note that further details are given in the next section,
which describes each of the dialog boxes used by the example pro-
gram):

1. Select the New Dialog item of the Edit menu to begin designing
the first dialog box. The editor will subsequently request an iden-
tifier (through one of its own dialog boxes); you should assign
each dialog box a unique identifier, since you must pass this
value to the system to display a specific dialog box from your
Program.
DesigningDialogBoxes 341 .

2. The new dialog box appears within the Dialog Box Editor win-
dow, which simulates the ozo7icr of the dialog box. You can move
the dialog box to the desired location relative to this window by
dragging it with the mouse pointer. Note that when the dialog
box is ultimately displayed by your program, it will appear at
the same relative position with respect to the lower left comer of
its owner, which is normally the client window.
3. When you click the mouse within the dialog box, a thick sizing
border will be drawn around its edges. The object currently sur-
rounded by this border is known as the scJecfcd object, and you
can adjust the dialog box to the desired size by manipulating the
edges of this border with the mouse in the same manner that
you resize a standard Presentation Manager window.
4. Select the Styles item of the Edit menu to assign or modify the
dialog box styles (the styles chosen for each of the dialog boxes
of the example program are described in the next section).
Add controls to the dialog window (such as push buttons,
text strings, and edit fields) by selecting each control from the

• Figure 8.2..
The Dialog Box Editor
•342 Programmer's Guide to the OS/2 Presentation Manager

Control menu. Use the mouse to drag a new control to the


desired location within the dialog window.
When you release the mouse button after dragging a control to
the desired location, the editor will automatically display one of
its own dialog boxes; you must enter an identifier for the control,
and you can optionally add or eliminate control styles.
The new control will initially be the selected object, and will
therefore be surrounded by a thick sizing border. You can use
this border to adjust the size of the control in the same marmer
that you adjusted the size of the dialog box itself.
At any time, you can select a control (or the entire dialog box) by
simply clicking the mouse within its borders. Once you have
selected an item, you can move it or adjust its size using the
sizing border; you can also alter its identifier or styles by choos-
ing the Styles item of the Edit menu.
When you have completed designing a given dialog box, you
can create another one through the New Dialog Box item of the
Edit menu.
10. When you have finished the last dialog box, you can save your
data through the File menu, specifying the name of a resource
file. The editor not only writes a resource file (with the .RES ex-
tension), but more importantly, it generates a resource script file
(with the .DLG extension). For example, if you enter the name
APP, the editor will generate the resource file APP.RES, and the
resource script APP.DLG (similar to the one in Figure 8.1).

Once you have generated a resource script using the Dialog Box
Editor, you can convert this file to binary format and insert the data into
the executable program, as described in Chapter 7. Since the current
version of the example program also defines resources for a menu and
an accelerator, the script for the dialog boxes is included within the
general resource script (Figure 8.36, listed at the end of the chapter),
using the following statement:

rcinclude FIG8 35.DLG


DesigningDialogBoxes 343 .

This statement assumes that the script file generated by the Dialog
Box Editor is FIG8 35.DLG. When the resource compiler encounters
this statement, it r=ads and processes the dialog box script file and
adds the dialog box templates to the collection of resources in the
.RES file that will ultimately be inserted into the executable program
file. (Note that the .RES resource file generated directly by the Dialog
Box Editor, which initially would contain only dialog box resources,
is not the one loaded into the .EXE file of the example program.
However, you must save this file if you want to add, remove, or
modify dialog box definitions, since the current version of the Dialog
Box Editor reads in the .RES file rather than the .DLG file when you
specify an existing file name.) For details, see the general resource
file (Figure 8.36), the dialog resource script (Figure 8.35), and the
MAKE file (Figure 8.33) listed at the end of the chapter.
Once you have designed the collection of dialog boxes and have
placed the dialog box templates within resource segments in the ex-
ecutable file, you can display any of these dialog boxes and use it to col-
1ect data from the user. Before explaining how to display and manage
dialog boxes, however, the following section describes each of the
dialog boxes used within the example program so that you will be able
to create them; the following section also serves to describe many of the
specific control windows and styles that you can choose from the Dia-
log Box Editor.

The Program Dialog Boxes


This section illustrates each of the dialog boxes designed using the
Dialog Box Editor and displayed by the example program. These dialog
boxes use only a subset of the large number of control windows, op-
tions, and styles that you can select through the Dialog Box Editor. You
can learn about the other features by experimenting with the Dialog
Box Editor and using its help facility, and by referring to the technical
documentation.
Note that the tables given in this section list the identifier for each
dialog window and each child control window; these values are as-
signed when the objects are created in the Dialog Box Editor. Some of
the identifiers must be used within the program to reference the cor-
responding objects; such identifiers are given values beginning with
• 344 Programmer's Guide to the os/2Presentation
Manager

256, and corresponding constants are defined for these identifiers to


simplify using them within the C program. The constants are defined in
the program header file (Figure 8.37, at the end of the chapter), which is
included in the C source code of Figure 8.38. In contrast, the identifier
-1 is assigned to objects that do not need to be referenced within the
program (such as text controls containing strings that are never
changed).

The About Dialog Box


The About dialog box, which is displayed in response to the About
item of the File menu, serves to briefly identify and describe the pro-
gram. This dialog box is illustrated in Figure 8.3, and its features are
summarized in Table 8.1. The dialog box contains three control windows
that simply display text, and a single push button that is used to dismiss
the dialog box.
ThefirstcolumninTable8.1identifieseachobjectaccordingtothelabels
used in Figure 8.3. The second column describes the objects; note that the
first object is the dialog window itself, and the other objects are child con-
trol windows that are selected from the Control menu of the Dialog Box
Editor (the descriptions are the same as those listed in the Control menu).

• Figure 8.3..
The About dialog box
DesigningDialogBoxes 345 .

The third field gives the nuneric identifier, and the corresponding con-
stant if one has been defined (ID_ABOUTDLG is defined in the pro-
gram header file, listed in Figure 8.37, and DID_OK is defined in the
system header file PMWIN.H).
The final column lists all styles, features, or options that were
selected through the Styles item of the Dialog Box Editor Edit menu.
These styles are given exactly as they appear in the Dialog Box Editor.
For example, the first text control (labeled 1, and containing the string
``Presentation Manager'') was defined as shown in Figure 8.4.

• Table 8.1.. Features of the Abo1_t_ Dial9_gpr

IDof StylesITeatures/
Eiagbuerleig.3 5ybi:cotf Object Options
0 Dialog Box 256 Options
(ID_ABOUT- Dialog Frame
DLG)
1 Text control -1 Basic Styles
Text
Text Styles
Horiz. Centered
Top Aligned
2 Text control -1 Basic Styles
Text
Text Styles
Horiz. Centered
Top Aligned
3 Text control -1 Basic Styles
Text
Text Styles
Horiz. Centered
Top Aligned
4 Push-Button 1(DID OK) Types
Control Push Button
Options
Default
• 346 Programmer's Guide to the os/2Presentation
Manager

As you can see from Table 8.1, the About dialog box is given a d€.¢Jog
/r¢77te, which is the standard thin, double-line border normally used for
dialog boxes. Note that this is not a wide sizing border, and therefore
the user cannot resize the dialog box. Also, since the dialog box is not
given a title bar, the user cannot move it on the screen. The dialog box
identifier, 256 (ID_ABOUTDLG), will be passed to the system when the
program displays the dialog box.
The three text controls serve to display static text strings. These controls
are assigned styles so that the text they display is aligned at the top of the
control and is horizontauy centered. Since these three objects are not
manipulated by the program, they are given identification values of -1.
Finally, the push-button control is specified as a dc/##Jf push button.
A default push button is given a thicker border than a normal push but-
ton; also, if the user presses the Enter key, the system sends a message
bearing the identifier of the default push button. (If a dialog box con-
tains several push buttons, only one should be designated as default.)
As you will see, the system also sends a message accompanied by the ID
of this push button if the user clicks the mouse button with the pointer
within its borders. The user can therefore dismiss the About box either
by pressing Enter or by clicking on the button; the program also allows

• Figure 8.4..
The definition of the first text control in the About dialog box
DesigningDialogBoxes 347 .

theusertoremovethedialogboxbypressingtheEsckey.Thepushbut-
ton is assigned the identifier DID_OK, which is defined as 1 in the sys-
tem header file PMWIN.H and is the standard value used for a default
push button.

The Find Dialog Box


The Find dialog box is activated through the Find item of the
Search menu, and allows the user to enter a string, which the program
will attempt to find within the file. The dialog box is illustrated in Fig-
ure 8.5, and its features are listed in Table 8.2.
This dialog box contains an edit control (label 2), which allows the
user to enter a string and to perform normal editing operations, such as
deleting and backspacing over characters, and moving the cursor with
the arrow keys. The edit control is Je/f-¢J€.g7ied, meaning that characters
are entered beginning at the left edge of the control; it is also assigned
the ¢t4fo feor!.zo7i£¢J scroJZ style, which causes the characters to automat-
ically scroll left if the user reaches the right end of the field. Finally, it is
given a "¢rgl.71, which means that a box will be drawn around the entire
edit control.

11

i......... .................`.'.'.'.'.'.'.'.'.I.'.'.'.`.'.....,'.'.'.''`'''''`..'.'''''''''''..''`''''''''''''.'.'.''.'-``'..'''.'''' i

i Find: I, li

(M- G-i----------iI i
11

• Figure 8.5..
The Find dialog box
• 348 Programmer's Guide to the os/2PresentationManager

This dialog box is given two push buttons. The push button labeled
``Find" is made the dc/##Jf push button; therefore, if the user presses the
Enter key or clicks on this button, the system will send a message con-
taining the button's ID (DID_OK). The push button labeled ``Esc=Can-
cel" is given the same ID that is sent when the user presses Esc
(DID_CANCEL); as you will see, when the program receives a message
with this ID, it immediately removes the dialog window without per-
forming the find operation. Therefore, the user can abort the operation
by clicking on the Esc=Cancel button or by pressing Esc.

Tfrble 8.2.. Feature_s of the Find Dialog Box

Label in IODbJgefct 8t#ieoslFse ature s/


Figure 8.5
0 Dialog Box 258 (ID_FIND- Styles
DLG) Dialog Frame
1 Text control -1 Basic styles
Text
Text Styles
Left Aligned
Top Aligned
2 Edit control 258 (ID_FIND-Text Alignment
EDIT) Left Aligned
Options
Auto Horiz. from
Margin
3 Push-Button 1(DIDOK) Types
Control Push Button
Options
Default
4 Push-Button 2 (DID_CAN- Types
Control CEL) Push Button
DesigningDialogBoxes 349 .

The Go to Line Dialog Box


The Go to Line dialog box is displayed through the Go to Line
item of the Search menu. This dialog box allows the user to enter the
target line number, or to abort the operation and return to the applica-
tion. It is illustrated in Figure 8.6, and its features are summarized in
Table 8.3. This dialog box contains the same features as the Find dialog
box, described in the previous section.

The Save As Dialog Box


The Save As dialog box appears when the user chooses the Save
As item of the File menu. This dialog box displays the current drive and
directory and allows the user to enter the name under which the current
file is to be saved. This dialog box is shown in Figure 8.7, and is
described in Table 8.4.
All of the controls and styles assigned to the Save As dialog box have
been explained in the previous sections. Note, however, that the first
text control (label 1) is given a unique identifier (ID_SAVEASCD),

i...................................'..................................-..;GotoLineNumber:|lI

: GEED Esc=Cance,
I I............................

34

• Figure 8.6..
The Go to Line dialog box
• 350 Programmer's Guide to the os/2 Presentation Manager

• Table 8.3.. F±r± of the Go to Line Dpi±g__Pox

IDof StylesITeatures/
Eiagbuerleig.6 5ybi:c:f Object Options
Dialog Box 259 (ID_GO- Styles
TODLG) Dialog Frame
Text control -1 Basic Styles
Text
Text Styles
Left Aligned
Top Aligned
Edit control 259 (ID_GO- Text Alignment
TOEDIT) Left Aligned
Options
Auto Horiz. froll
Margin
Push-Button 1(DIDOK) Types
Control Push Button
Options
Default
Push-Button 2 (DID_CAN- Types
Control CEL) Push Button

Current Directory: C:`PGPM

-E=
Save File AS:

- llli

...................................I.................................................I..............................................i

\1

• Figure 8.7..
The Save As dialog box
DesigningDialogBoxes 351 .

• Table 8.4.. Features o the Save As DialEL

ID of Stylesffeatures/
Efgbuerleig.7 5ybi:c?f Obj ect Options
0 Dialog Box 257 (ID_SAVE-Options
ASDLG) Dialog Frame
1 Text control 258 (ID_SAVE-Basic styles
ASCD) Text
Text Styles
Left Aligned
Top Aligned
2 Text control -1 Basic Styles
Text
Text Styles
Left Aligned
Top Aligned
3 Edit control 257 (ID_SAVE-Text Alignment
ASEDIT) Left Aligned
Options
Auto Horiz. Scron
Margin
4 Push-Button 1(DIDOK) Types
Control Push Button
Options
Default
5 Push-Button 2 (DID_CAN- Types
Control CEL) Push Button

rather than being assigned -1 as in the previous dialog window. A


unique identifier is required because the control is used to display the
current program directory, and it must therefore be accessed from
the application. (Note that the identifier needs to be unique only among
the identifiers belonging to the same dialog box.)
•352 Programmer's Guide to the OS/2 Presentation Manager

The Open Dialog Box


The Open dialog box is activated when the user selects the Open
item of the File menu; it is illustrated in Figure 8.8 and described in
Table 8.5.

• Figure 8.8..
The Open dialog box

The Open dialog box displays the current drive and directory and al-
lows the user to enter the name of the file that is to be opened. In addi-
tion to the controls contained in the dialog boxes described previously,
this dialog box includes a list box. The list box displays all files that have
a .C or .TXT extension within the current directory, and contains a verti-
cal scroll bar that can be used to scroll through the list. The list box also
displays all subdirectories (including the parent directory) belonging to
the current directory, and the letters of all disk drives that are currently
installed.
If the user highlights a file name ®y moving the highlight to the item
with the arrow keys or by clicking on the item with the mouse), the pro-
gram displays this name automatically in the edit control. If the user
selects a file name by pressing Enter when the name is highlighted, or
by double-clicking on the item, the program opens the file and removes
the dialog box. If the user selects a directory name in the same manner
DesigningDia]logBoxes 353 .

• Table 8.5.. Features of the Open Dialog Box

Label in Type of IDof Styles/Features/


Figure8.8 Object Object Options
0 Dialog Box 260 Styles
(ID OPEN- Dialog Frame
DLG_)
Text control -1 Basic Styles
Text
Text Styles
Left Aligned
Top Aligned
Edit control 260 Text Alignment
(ID OPEN- Left Aligned
EDir) Options
Auto Horiz. from
Margin
Text control -1 Basic Styles
Text
Text Styles
Left Aligned
Top Aligned
Text control 261 Basic Styles
(ID OPEN- Text
CD) Text styles
Left Aligned
Top Aligned
List-Box 262
Control (ID OPEN-
LISF)
Push-Button 1 Types
Control (DID OK) Push Button
Options
Default
Push-Button 2 Types
Control (DID CAN- Push Button
CEL)
• 354 Programmer's Guide to the os/2PresentationManager

(by pressing Enter or double-clicking), the program changes to this


directory and displays the files contained in the new directory. Finally, if
the user similarly selects a drive letter, the program changes to this
drive and displays the files in the current directory of the new drive.
The list box is not assigned any styles. Note that the user can use the Tab
key to move between the edit control, the list box, and the push buttons.

Displaying a Dialog Box


The menu and accelerator tables are automatically loaded at the begin-
ning of the program, when the standard window is created by the can to
Wincreatestdwindow. Since, however, a dialog window is a temporary
object, you must explicitly load it each time you want it displayed.
A dialog window is loaded and displayed through the Presentation
Manager function WinDlgBox (Figure 8.9). For example, the routine
that processes the About menu item simply calls WinDlgBox to display
the About dialog box (illustrated in Figure 8.3), as follows:

WinDlgBox
(HWND DESKTOP, /* Handle of parent window: */
/* desktop. */
t"ryd I / * Handle of owner: client. */
Aboutproc, / * Address of dialog procedure. */
NULL ' / * Resource module: the .EXE file. */
ID ABOUTDLG, /* Name ID of dialog window: About.*/
NULL) ,. /* Pointer to procedure data: n/a. */

When the client window procedure makes this call, the system dis-
plays a dialog box that conforms to the template stored as a resource in
the .EXE file. The value NULL, passed as the fourth parameter, indicates
that the dialog resource is located in the .EXE file, rather than in
a dynamic-link module. Note that the dialog-box identifier passed as
the fifth parameter (ID_ABOUTDLG) is the same value assigned to the
dialog box within the resource script.
The third parameter supplies the address of a diezog proccdt/rc; as
you will see in the next section, the dialog procedure is a function that
DesigningDialogBoxes 355 .

WinDlgBox
Purpose..
Loads, displays, and processes a dialog box.

Prototype,
USHORT APIENTRY WinDlgBox
(IIWND hwndparent , Handle of the parent window (usually
HWND DESKTOP).
IIWND hwndowner , Handle:ftheownerwindow(usuauy
the client window).
PFNWP pfnDlgproc, Address of the dialog procedure.
"ODULE hood, Handle of the module containing the
resource for the dialog box; if the
resource is contained in the .EXE file,
this value should be NULL; if the
resource is in a dynamic-link hbrary
file, this parameter should be assigned
the handle returned by
DosLoadModule.
USHORT idDlg, The dialog-box identifier (that is, the
ID assigned to the dialog box in the
resource script).
pvolD pcreateparams) ,. A pointer to dialog procedure data, or
NULL if no data is passed to the
dialog procedure.

Return Value ..
The value that the dialog procedure passes as the second
parameter to WinDismissDlg, or DID_ERROR if an error
occurred.

Notes..
This function does not return until the application dialog
procedure issues the function WinDismissDlg.

Relate d Functions ..
WinDismissDlg (Figure 8.11 )

• Figure 8.9..
The W±nDLgBox Presentation Manager f unction
• 356 Programmer's Guide to the os/2 PresentationManager

you write to process the messages sent to the dialog box window. Win-
DlgBox does not return control until the dialog procedure explicitly dis-
misses it (through the function WinDismissDlg, discussed in the next
section). While the dialog box is displayed-and the dialog procedure is
processing the messages it is sent-the user cannot switch the focus to
another window within the current application (such a dialog box is
described as 777od¢J).
The first parameter supplies the handle of the parent of the dia-
log box. Since the desktop window (the entire screen, identified by
HWND_DESKTOP) is assigned as the parent, the dialog box is a top-
level window and can appear outside the boundaries of the
application's standard window. The second parameter specifies that
the owner of the dialog window is the client window; accordingly, the
dialog box will appear in the same position relative to the lower left
corner of the client window that it appeared relative to the simulated
owner window in the Dialog Box Editor (that is, the coordinates for the
dialog-box position that are written to the resource script are relative to
the lower left corner of the owning window). Note that this chapter ex-
plains only one of several methods that can be used to display a dialog
box under the Presentation Manager.

• MANAGINGADIALOGBOX
Once the system loads and displays a dialog box in response to the
WinDlgBox function, all messages sent to the dialog-box window are
received by the dialog procedure. A dialog box is thus managed by the
associated dialog procedure in the same way that a client window is
managed by the client window procedure assigned to the window's
class. A dialog procedure has the following features in common with a
client window procedure:

• Adialog procedure is passed the same set of parameters passed


to a window procedure, namely:
hwnd The handle of the dialog window
msg The message identifier
DesigningDialogBoxes 357 .

mpl Message-specific information


mp2 More message-specific information

A dialog procedure may process a given message and return con-


trol to the system, or it may pass a message to the system for
default processing.
• The name of each dialog procedure mustbe listed underthe EX-
PORTS statement of the linker definition file (see Figure 8.34).

Although a dialog procedure is quite similar to a standard window


procedure, the following are two important differences:

• When a dialog window is first displayed, the dialog procedure


receives the WM_INITDLG message (explained later) rather
than the WM_CREATE message.
• Whenyou pass a message to the system for default processing
from a dialog procedure, you must call the function WinDefDlg-
Proc (Figure 8.10) rather than WinDefwindowproc.

When the dialog procedure issues a return statement, control reverts


to the Presentation Manager; the dialog box, however, remains active
and visible, and messages continue to be sent to the dialog procedure
(also, as mentioned previously, during this time the user is unable to
switch the focus to another window belonging to the same application).
To remove the dialog box, the dialog procedure must call the function
WinDismissDlg (Figure 8.11). Once the dialog box has been removed
by calling this function, the keyboard focus reverts to the client win-
dow, and the call to WinDlgBox returns to the client window proce-
dure. Note that the value you assign to the second parameter of
WinDismissDlg is the value that is then returned by WinDlgBox. Ac-
cordingly, the dialog procedure can communicate information to the client
window procedure; for example, it can return TRUE or FALSE, indicating
whether the user pressed the Ok push button or the Cancel push button to
dismiss the dialog box (details are given in the following section).
The following section describes each of the dialog procedures of the
example program that are used to implement menu commands, and
shows how to process a number of the messages that may be received
by a dialog procedure.
• 358 Programmer's Guide to the os/2 PresentationManager

WinDefDlgproc
Purpose..
Provides default processing for a message sent to a dialog
procedure.

Prototype..
ULONG APIENTRY WinDefDlgproc
(IIWND hwndDlg, Dialog window handle.
USHORT msgid, Message identifier.
REARAM mpl , Message-specific information.
MPARAM mp2 ) ,. Message-specific information.

Return Value ..
The message return data; the meaning of this value depends
upon the message.

Notes..
This function is called by a dialog procedure; the four
parameters passed to the function should be the s¢777c as the
parameters passed to the dialog procedure. The function is
analogous to WinDefwindowproc, called by normal win-
dow procedures.

Related Functions ..
WinDefwindowproc (Figure 2.17)

• Figure 8.10..
The W±nDefDlgproc Presentation Manager f unction
DesigningDialogBoxes 359 .

WinDismissDlg
Purpose..
Removes the current dialog box and causes the function
WinDlgBox to return control.

Prototype..
BO0L APIENTRY WinDismissDlg
(HWND hwndDlg, Dialog window handle.
USHORT usResult) ,. Value that is to be returned by
WinDlgBox.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
This function hides but does not actually destroy the dialog
box; the dialog box is subsequently destroyed when control
reverts to the function WinDlgBox, which was originally
used to display the dialog box.

Related Functions ..
WinDlgBox (Figure 8.9)

• Figure 8.11..
The WinDis:rr\issD18 Presentation Manager function

The Commands
Now that the general techniques for designing, displaying, and
managing dialog boxes have been described, this section discusses each
of the menu commands of the example program that is implemented
using a dialog box. Note that the dialog box for each of the following
commands was discussed in the section on The Program Dialog Boxes,
earlier in the chapter.
• 360 Programmer's Guide,to the os/2 Presentation Manager

As described in Chapter 7, the menu commands are executed by the


function Command, which processes the messages sent from the menu
control. This function consists of a large switch statement that branches
to the appropriate routine based upon the identification of the selected
menu item. Many of these routines were already discussed in Chapter 7;
this section discusses the routines that display dialog boxes. It also
describes each of the dialog procedures that process messages once the
associated dialog box has been displayed.

The About Command


The routine for the About menu command is located within the
Command function of the example program, and for convenience is
also listed in Figure 8.12. This routine is activated whenever the
WM_COMMAND message has the identifier ID_ABOUT, indicating
that the user has selected the About item of the File submenu. The
routine simply calls WinDlgBox to display a dialog box and returns.
The call to WinDlgBox was described previously, in the section on Dis-
playing a Dialog Box.
The dialog procedure for the About dialog box is named Aboutproc,
and is listed in Figure 8.13. This function processes the WM_COM-
MAND message (Figure 7.11), and calls WinDefDlgproc to pass all
other messages to the system for default processing. As explained in

case ID ABOUT: /* 'About' item 'File' submenu.

/* Display 'About' box using a dialog box.


WinDlgBox
(HWND DESKTOP, /* Handle of parent window: desktop.
hwnd ' /* Handle of owner: client.
Aboutproc , /* Dialog procedure.
NULL, /* Resource module: the .EXE file.
ID AB0UTDLG, /* Name ID of dialog window: About.
NUIL) ; /* Pointer to procedure data: n/a.
return FALSE;

• Figure 8.12..
The routine for the About menu command
DesigningDialogBoxes 361 .

Chapter 7, the WM_COMMAND message is accompanied by a com-


mand code indicating the specific event that occurred; this value is ex-
tracted using the COMMANDMSG macro, as follows:

COMMANDMSG ( &msg) ->cmd

The Aboutproc function processes two command values: DID_OK and


DID CANCEL.
DID_OK is the identifier that was assigned to the Ok push button in
the dialog resource script. Accordingly, a WM_COMMAND message
bearing this identifier is sent whenever this button is selected. (The user
can select the button by clicking on it with the mouse, or by pressing the
Spacebar when the button has the focus; this button automatically has
the focus when the dialog box is first displayed.) Note that the Ok push

MRESULT EXPENTRY Aboutproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
/*
Prcicess dialog messages for the 'About' dialog box.
*/
(
switch (msg)
(
/*** Process WM COMMAND messages sent by 'About' dialog box controls. ***/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Ok' button or pressed Enter key. ********/
case DID OK:

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:
Win5ismissDlg (hwnd,TRUE) ;
return FALSE;
default:
return FALSE;
)
default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

} /* end Aboutproc */

• Figure 8.13..
The function Atooulproc of the example program
• 362 Programmer's Guide to the os/2 Presentation Manager

button was designated as the default push button (this style was
selected from the Dialog Box Editor); therefore, the system also sends
the identifier of this button if the user presses the Enter key.
The system sends a WM_COMMAND message with the DID_CAN-
CEL command value whenever the user presses the Esc key. (As you
will see in the next routine, the system also sends this co]rm.and if the
user has selected a button that was assigned the value DID_CANCEL as
its identifier; the About box, however, contains no such button.)
If Aboutproc receives either of these two corrmand messages, it
simply calls WinDismissDlg to remove the dialog box. Accordingly,
the user can dismiss the dialog box by selecting the Ok button, or by
pressing either Enter or Esc.

The Find and Find Next Commands


The routine that processes the Find command of the Search sub-
menu is listed in Figure 8.14. This command causes the program to
search for the first instance of the specified string that occurs in the
file beyond the current cursor position. The routine calls WinDlgBox
to display a dialog box, and to activate a dialog procedure that ob-
tains the string from the user and searches for the string within the
file. If the dialog procedure successfully locates the string, it moves
the cursor just beyond the position of this string within the file. If the
new cursor position is outside the portion of the file currently dis-
played in the window, the dialog procedure returns a value of TRUE,
indicating that the window display must be updated. In this case, the
Find routine invalidates the entire window, and sends messages to
update the horizontal and vertical scroll bar positions.
The dialog procedure that manages the Find dialog box, Findproc, is
listed in Figure 8.15. This procedure processes the same two
WM_COMMAND messages described in the previous section. The
DID OK command is sent if the user selects the Find button (which was
assigned the identifier DID_OK and is also the default push button), or
if the user presses the Enter key. The routine processes this message by
proceeding to search for the specified text. If, however, the routine
receives the DID_CANCEL command, it summarily dismisses the
dialog box without performing the search.
DesigningDialogBoxes 363 .

case ID FIND: /* 'Find' item of 'Search' submenu. */

/* Process command through a dialog box.


Result = WinDlgBox
(HWND DESKTOP /* Handle of parent window: desktop.
hwnd ' /* Handle of owner: client.
Findproc , /* Dialog procedure.
NULL, /* Resource module: the .EXE file.
ID FINDDLG, /* Name ID of dialog window: Find.
NUIL) ; /* Pointer to procedure data: n/a.
if (:Result) /* Window needs repainting.
(
/* Redisplay window for new position in file.
WinlnvalidateRect /* Invalidate window.
(hwnd, /* Handle of client window.
NULL, /* Invalidate ENTIRE window.
FALSE) ;

Winupdatewindow (hwnd) ; /* Force updating of window.

WinsendMsg /* Set horizontal scroll bar position.


(HHScroll,
SBM SETPOS,
MPFkoM2SHORT (Firstcol, O) ,
0);

WinsendMsg /* Set vertical scroll bar position. */


(HVscroll,
SBM SETPOS,
MPFkoM2SHORT (TopLine, 0) ,
0);
)

return FALSE;

case ID FINDNEXT: /* 'Find Next' item of 'Search' submenu. */

/* Search for string -- update cursor position if found. */


if (SearchBuf (Findstring, &CursorLine, &Cursorcol) == FALSE)
(
/* String not found. */
WinMessageBox
(HWND DESKTOP,
HFrame,
"String not found",
''PM Text Editor",
0,
MB_OK I
MB ICONASTERISK) ;

return FALSE;
)

• Figure 8.1L.I i..


The routines for the Find and Find Next menu commands
• 364 Programmer's Guide to the os/2PresentationManager

/* Adjust 'TopLine' for position of found string. */


if (CursorLine < TopLine I I
CursorLine >= TopLine + ywin/ycharTot)
(
TopLine = max (O,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Update = TRUE;
)

/* Adjust 'Firstcol' for position of found string. */


if (Cursorcol < Firstcol I I
Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = max (0,Cursorcol - (xwin/xchar)/2) ;
Firstcol = min (Firstcol,FirstcolMax) ;
Update = TRUE;
)

/* Update window if necessary to display a new file position. */


if (Update)
(
WinlnvalidateRect /* Invalidate whole window. */
( hwnd ,
NULL,
FALSE) ;

Winupdatewindow (hwnd) ; /* Force immediate updating. */


WinsendMsg /* Adjust horizontal scroll bar. */
(HHScroll,
SBM SETPOS,
MPF`koM2SHORT (Firstcol, 0) ,
0);
WinsendMsg /* Adjust vertical scroll bar. */
(HVscroll
SBM SETPOS,
MPFEOM2SHORT (TopLine, 0) ,
0);
)

/* Reposition the cursor. */


Wincreatecursor
( hwnd '
(Cursorcol - Firstcol) * xchar,
ywin - (CursorLine - TopLine + 1) * ycharTot,
0,
0,
CURSOR SETPOS,
NULL) ;

return FALSE;

• Figure 8.14..
The routines for the Find and Find Next menu commands (continued)
DesigningDialogBoxes 365 .

.`:!``:I:;T'I,'.` F.XPENTRY Findproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
.I

i;:::5R:u5:::t:2±;FALSE; /: ::::Si:::::t::a::::£:r°:i::::r::d:::en::::i. :/
switch (msg)
(

/* Process WM COMMAND messages sent by dialog controls. *****************/


case WM COMMAND:

switch (COMMANDMSG(&msg) ->cmd)


(
/*** User clicked on 'Find' button or pressed Enter key. ******/
case DID OK:

/* Obtain text from 'Find:I edit box.


WinQuerywindowText
(WinwindowFromlD (hwnd, ID_FINDEDIT) ,
sizeof (Findstring) ,
Findstring) ;

/* If search string empty, return immediately.


if (Findstring [0] == '\0')
return FALSE;

/* Search for string.


if (SearchBuf (Findstring, &CursorLine, &Cursorcol) ==
FALSE)
(
/* Display message if string not found.
WinMessageBox
(HWND DESKTOP,
hwnd, /* Note: parent is dialog window*/
"String not found",
''PM Text Editor",
0,
MB OK I
MB-ICONASTERISK) ;

/* Remove dialog box.


WinDismissDlg (hwnd, FALSE) ;
return FALSE;
)

/* Adjust 'TopLine' for new cursor position.


if (CursorLine < TopLine I I
CursorLine >= TopLine + ywin/ycharTot)
(
TopLine = max (0,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Update = TRUE;
)

/* Adjust 'Firstcol' for new cursor position. */

• Figure 8.15..
The function Findproc of the exanple program
• 366 Programmer's Guide to the os/2 Presentation Manager

if (Cursorcol < Firstcol I I


Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = max (O,Cursorcol - (xwin/xchar)/2) ;
Firstcol = min (Firstcol,FirstcolMax) ;
Update = TRUE;
)
/* Remove dialog box, returning flag indicating */
/* whether window must be updated. */
WinDismissDlg (hwnd, Update) ;
return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. */


case DID CANCEL:

/* Remove dialog box.


WinDismissDlg (hwnd,FALSE) ;
return FALSE;
default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit field. ********************/


case WM CONTROL:

switch (SHORTIFROMMP (mpl) )


(
/*** Message sent by edit box. ********************************/
case ID FINDEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:
/*-Get new text. */
WinQuerywindowText
((HWND) mp2,
2,
Buf fer) ;
/* Enable 'Find' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;
)

/*** Process WM INITDLG message sent when dialog box first displayed. ***/

• Figure 8.15:
The function F±ndproc of the example program (continued)
DesigningDialogBoxes 367 .

case WM INITDLG:

/* Display initial value of 'Findstring' in edit box. */


WinsetwindowText
(WinwindowFromlD (hwnd, ID_FINDEDIT) ,
Findstring) ;
default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

) ,;* end Findproc */

• Figure 8..15:
The function Findproc of the example program (continued)

If the dialog procedure receives the DID_OK command, it first calls


the WinQuerywindowText Presentation Manager function (Figure
8.16) to extract the string that the user entered into the edit control. This
function call copies the string from the dialog box edit control into the
program buffer Findstring. To search for the string within the file buff-
er, the routine then calls the function SearchBuf, which belongs to the
buffer-management module and is listed in Figure 8.17.
SearchBuf is passed the search string and the ¢ddrcsscs of the vari-
ables containing the current cursor row and column. If this function
finds the string within the file buffer, it adjusts the values of the vari-
ables containing the cursor position so that the cursor is positioned
immediately ¢fcr the matching string, and it returns the value TRUE. If
the function does not find the string, it returns FALSE without alter-
ing the cursor-position variables.
If SearchBuf returns FALSE, the dialog procedure displays a mes-
sage box to inform the user that the string was not found, and then dis-
misses the dialog box, passing back a code of FALSE so that the client
procedure will not update the window display. If, however, SearchBuf
returns TRUE, the dialog procedure adjusts the global variables Top-
Line and Firstcol zf the new cursor position falls outside the current
boundaries of the window. (If TopLine and Firstcol must be adjusted,
they are given values that will place the cursor within the center of the
window.) The routine then dismisses the dialog box, returning a code
indicating whether the client window procedure must update the win-
dow display.
• 368 Programmer's Guide to the os/2 Presentation Manager

Note that the function SearchBuf may have changed the values of
Cursorcol or CursorLine. The cursor is actually placed at this new
position by the function SetFocus, which is automatically activated
through the WM_SETFOCUS message sent when the client window
regains the keyboard focus after the dialog window is removed.
In general, control windows notify their owners of significant events
either through the WM_COMMAND message (already discussed), or
through the WM_CONTROL message (described in Figure 8.18). The
Findproc dialog procedure processes the WM_CONTROL message sent

WinQuerywindowText
Purpose,
Copies the text associated with a window into a program
buffer.

Prototype..
SHORT APIENTRY WinQuerywindowText
(HWND hwnd, Window handle.
SHORT cchBufferMax, Length of buffer to receive text.
pSz pszBuffer) ,. Address of buffer to receive text.

Return Value ..
The length of the window text copied into the buffer.

Notes..
This function will not copy more than ccBufferMax-1
characters.

Relate d Functions ..
WinsetwindowText (Figure 7.18)

• Figure 8.16..
The WinQnery:WindowText Presentation Manager f unction
DesigningDialogBoxes 369 .

by the edit control window whenever the text it contains is altered (the
text can be altered either by the user or by the program through the
WinsetwindowText function).
Whenever its text is modified, the edit control sends a WM_CONTROL
message with its own identifier (ID_FINDEDIT) in the low-order word of
mpl, and the code EN_CIIANGE in the high-order word of mpl. The
dialog procedure processes this message by obtaining the first character
containedintheeditfield(throughthefunctionWinQuerywindowText).
It then calls WinEnablewindow (Figure 4.10) to c7i¢Z7Zc the Find button
if the string contains at least one character or to d{.s¢bJe the button if the
string is empty. When the Find button is disabled, its text is displayed in a
halftone font, and the system does 72of send the DID_OK command when

int SearchBuf (char *Findstring, PSHORT Line, PSHORT Col)

Searches f ile buf fer for string 'Findstring', from position given by
'I..Lne' and 'Column'. If string is found, updates 'Line' and 'Col' to
pos;ition immediately after the string in buffer, and returns TRUE. If
string is not found, function does not update 'Line' and 'Col', and it
returns FALSE.

(
register int i, j;
char far *Fptrch;
Fptrch = LineTable [*Line].LineAddress + *Col;
i = i.Line;
for (;;)
(
while (*Fptrch)
(
for (j = 0; Findstring [j] == Fptrch [j] && Findstring [j]; ++j)

if (Findstiing [j] == '\0')


(
*Line -i;
*Col = Fptrch + j -LineTable [i].LineAddress;
return TRUE;
)
++Fptrch ;
)
if (++i > LastLine)
return FALSE;
Fptrch LineTable [i].LineAddress;
)

} /* end SearchBuf */

• Figure 8.17..
The function Sea;rch;But of the exanple program
• 370 Programmer's Guide tothe os/2PresentationManager

the button is selected or the user presses Enter. Accordingly, the user
does not attempt to search for a NULL string.
Finally, the Findproc function processes the WM_INITDLG message
(Figure 8.19), which is sent when the dialog box is first displayed. The
initialization routine calls WinsetwindowText to set the text in the edit
control to the string currently contained in Findstring (which is either
empty or contains a string from a previous execution of the Find menu
command).

WM CONTROL
Purpose..
This message is sent by a control window to its owner to
report a significant event.

Parameters..
MPAEun mpl
low-order word: Identifier of control window.
high-order word: The notify code, which indicates the
specific event; the meaning of this field
depends upon the control window
class.
REJ- mp2 Control-specific information.

Return Value ..
NULL.

Notes..
See also a similar message, WM_COMMAND (Figure 7.17).

• Figure 8.18..
The WM_CONTROL Presentation Manager message
DesigningDialogBoxes 371 .

WM INITDLG
Puxpose..
This message is sent by the system to a dialog window when
it is first created, before it becomes visible.

Parameters..
REA- mpl Handle of the dialog control window that
will receive the initial keyboard focus.
REJ- mp2 Pointer to an optional data structure passed
as the last parameter to WinDlgBox.

Return Value ..
The dialog procedure should return TRUE if it has assigned
the focus to a control window other than that given in mpl
(by calling WinsetFocus; this would be done to alter the con-
trol that receives the initial keyboard focus). The procedure
should return FALSE if it has 71of changed the focus.

Notes..
This message allows the dialog procedure to perform in-
itialization tasks.

• Figure 8.19..
The WM_INITDLG Presentation Manager message

The Find Next Command


The routine that processes the Find Next command of the Search
submenu is listed in Figure 8.14, following the code that processes
the Find command. This routine searches for the next ocourrence of the
string that was specified by the most recent activation of the Find com-
mand. Since Findstring already contains a value, this routine does not
display a dialog box; it is described here, however, because it is closely
related to the Find routine.
The code for the Find Next command performs the same sequence
of steps employed by the Find routine to search for the string and to
•372 Programmer's Guide to the OS/2 Presentation Manager

update the window display. Note, however, that the function Win-
Createcursor is called to explicitly reposition the cursor; this step is
necessary because the routine does not display a dialog box, and there-
fore the SetFocus function is not automatically invoked as the focus is
passed from the dialog window back to the client window.

The Go to Line Command


The code that processes the Go to Line menu item is listed in Fig-
ure 8.20. This command moves the cursor to the first column of the

case ID GOTOLINE: /* 'Go to Line' item of 'Search' submenu. */

/* Process command through a dialog box. **********************/


Result = WinDlgBox /* Display dialog box. */
(HWND DESKTOP, /* Handle of parent window: desktop. */
hwnd , /* Handle of owner: client. */
Gotoproc , /* Dialog procedure. */
NULL' /* Resource module: the .EXE file. */
ID GOTODLG, /* Name ID of dialog window: Goto. */
NUE:L) ; /* Pointer to procedure data: n/a. */
/* If command executed, force updating of entire window. */
if (Result)
(
WinlnvalidateRect /* Invalidate entire window. */
( hwnd ,
NULL,
FALSE) ;
Winupdatewindow (hwnd) ; /* Force window update. */
Winse?£¥§8ro]],/* Set horizontal scroll bar position. */
SBM SETPOS,
MPFEOM2SHORT (Firstcol,0) ,
0);

W±nse?S¥;gro]L,/* Set vertical scroll bar position. */


SBM SETPOS,
MPFEOM2SHORT (TopLine, 0) ,
0);

return FALSE;

• Figure 8.20..
The routine for the Go to Line menu command
DesigningDialogBoxes 373 .

specified line number. Most of the processing for this command occurs
within the dialog procedure, which returns a value of TRUE if the com-
mand was executed (the user selected the Go to Line push button), or
FALSE if the command was aborted (the user selected the Cancel but-
ton). If the command was executed, as indicated by a TRUE return
value, the routine invalidates the entire window to force the Paint func-
tion to display the appropriate data for the new file position.
The dialog procedure for this command is named Gotoproc, and it is
listed in Figure 8.21. This function is quite similar to the dialog proce-
dure for the Find command, discussed in the previous section. If the
procedure receives a WM_COMMAND message with the DID_OK
command, it extracts the text from the edit control and calls the C
library function atoi to convert the string to a numeric value. If the
resulting line number is valid (that is, greater than 0), it is first decre-
mented because the user counts lines beginning with 1, whereas the
program enumerates lines beginning with 0. If the number is invalid,
the function simply returns, which terminates processing of the current
message but causes the dialog box to remain active.
The routine next sets the global variable CursorLine to the newly ob-
tained line-number value, and adjusts TopLine so that the line contain-
ingthecursorisdisplayedhalfwaydownthescreen.Finally,Cursorcol
and Firstcol are set so that the first colu]rm will be visible and will con-
tain the cursor, and the dialog box is dismissed, returning a value of
TRUE to force the client window procedure to update the window dis-
play. (Note that when the dialog box is removed, the SetFocus function
performs the actual repositioning of the cursor.)
In the same manner as the Findproc function, Gotoproc processes
the WM_CONTROL message sent by the edit control when its text is
changed. This routine enables the Go to Line push button only if the
edit control contains at least one character.
Finally, Findproc processes the WM_INITDLG message. This routine
calls WinEnablewindow to initially disable the Go to Line button, since
the edit control does not yet contain text.
• 374 Programmer's Guidetothe os/2Presentation
Manager

MRESULT EXPENTRY Gotoproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
char NumberBuf [33];
char Buffer [2];
SHORT LineNumber;

switch (msg)
(
/*** Process WM_COMMAND messages sent by dialog controls. ***************/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Go to' button or pressed Enter key. *****/
case DID 0K:

/* Obtain text from 'Go to Line' edit box.


WinQuerywindowText
(WinwindowFromlD (hwnd, ID GOTOEDIT) ,
sizeof (NumberBuf ) ,
NumberBuf ) ;

/* Convert to numeric value and continue if > 0.


LineNumber = atoi (NumberBuf ) ;
if (LineNumber <= 0)
return FALSE;

/* Set global cursor and window position variables. */


--LineNumber ; ,
CursorLine = min (LastLine,LineNumber) ;
TopLine = max (0,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Cursorcol = Firstcol = 0;
/* Remove dialog box.
WinDismissDlg (hwnd, TRUE) ;
return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. */


case DID CANCEL:

/* Remove dialog box. */


WinDismissDlg (hwnd,FALSE) ;
return FALSE;
default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit field. ********************/


case WM CONTROL:

switch (SHORTIFROMMP (mpl) )

• Figure 8.21..
The function Gotoproc of the example progran
Designing Dialog Boxes 375.

(
case ID GOTOEDIT:
switch (SHORT2FROMMP (mpl) )
(
/*** User altered the text. *************************/
case 7!-gEF::; text. */
WinQuerywindowText
((END) mp2,
2,
Buf fer) ;
/* Enable 'Go to' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;
)

/*Jf* Process WM_INITDLG message sent when dialog box first displayed. ***/
case WM INITDLG:

/* Initially disable 'Go to' button (until text entered). */


WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;
return FALSE;

default:
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

} /* end Gotoproc */

® Figure 8®21..
Tire fu.nction Gotoproc of the exanple program (continued)

The Save As Command


The Save As command of the File submenu saves the current file
under a name that is specified by the user; this command can be used
either to change the file name or to assign a name to an untitled file when
performing the save operation. The routine that executes this command is
invoked when the user selects the Save As item from the File menu, or
• 376 Programmer's Guide to the os/2Presentation
Manager

when control drops through from the Save routine (the Save routine
precedes the Save As routine, and allows control to pass to the Save As
routine if the file is currently unnamed). The routine serves only to ac-
tivate the appropriate dialog box, and is listed in Figure 8.22.
The dialog procedure for the Save As command, SaveAsproc, is
listed in Figure 8.23. When the user selects the Save dialog button, this
function extracts the contents of the edit control, and-if the string is
not empty-it calls the function SaveFile (described in Chapter 7). If
SaveFile returns TRUE, indicating that it successfully saved the file
under the new name, the fully qualified version of this name is stored in
the global variable FileName, the new name is displayed in the title bar
(by calling ShowFileName), and the Modified flag is reset to 0. If Save-
File returns FALSE, the procedure displays a message box to inform the
user that the file could not be saved. Whether or not the save operation
was successful, the dialog box is dismissed.
SaveAsproc also processes the WM_CONTROL message that is sent
whenever the text in the edit control is modified. The routine that
processes this message performs the same tasks as the routines belong-
ing to the dialog procedures that have already been described.
Finally, the SaveAsproc function processes the WM_INITDLG mes-
sage to initialize the dialog box. The initialization routine first sends
the message EM_SETTEXTLIMIT (Figure 8.24) to the edit control. This
message is sent to an edit control of a dialog box to set the maximum
number of characters that can be entered into the control (either by the
user or by the program when it calls WinsetwindowText; the default
number of characters is 32). The maximum is set to the value PATH-
LENGTH (currently 128), so that the edit control can accommodate a

case ID SAVEAS: /* 'Save As' item of 'File' submenu. */

#n:I:S:=S message using a dialog box. */


(HWND DESKTOP /* Handle of parent window: desktop. */
hwnd ,
Saveasproc , /: E::::; Sfo::::::. client. :/
NULL, /* Resource module: the .EXE file. */
ID SAVEASDLG, /* Name ID of dialog window: Saveas.*/
NULL) ; /* Pointer to procedure data: n/a. */
return FALSE;

• Figure 8.22..
The routine for the Save As menu command
Designing Dialog Boxes 377.

MRESuljT EXPENTRY Saveasproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

Processes dialog messages for the 'Save As' dialog box.


*/

chai Filepath [PATHLENGTH]; /* Holds file path. */


char-CurDir [PATHLENGTH + 22] ; /* Holds contents of 'Current Directory' .*/
char Buffer [2]; /* Holds first character of entered file name. */
switch (msg)
(

/*** Process WM_COMMAND messages sent by dialog controls. ********************/


case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Save' button or pressed Enter key. ******/
case DID OK:

/* Obtain text from 'Save As' edit box. */


WinQuerywindowText
(WinwindowFromlD (hwnd, ID_SAVEASEDIT) ,
sizeof (Filepath) ,
Filepath) ;

/* If path string not empty, save file/remove dialog*/


if (Filepath [0])
(
*/
/* Save under the new name.
if (SaveFile (Filepath) == FALSE)

/* Display error message if save failed. */


WinMessageBox
(HWND DESKTOP,
hwnd ,
''Error --Cannot Save File",
''PM Text Editor",
0'
MB OK I
MB-ICONASTERISK) ;
else
(
/* Store fully qualified path name.
Qualify (Filepath, FileName) ;

/* Display the new name in title bar.


ShowFileName () ;

/* Reset 'Modified' flag.


Modified = 0;
)

*/
/* Remove dialog box.
WinDismissDlg (hwnd, TRUE) ;

• Figure 8.23..
The function SaveALsproc of the example program
• 378 Programmer's Guide to the os/2Presentation
Manager

return FALSE;
)

return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:

/* Remove the dialog box.


WinDismissDlg (hwnd,TRUE) ;
return FALSE;
default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit box. **********************/

case WM CONTROL:
switch (SHORTIFROMMP (mpl) )
(
/*** Message sent by edit box. ********************************/
case ID SAVEASEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:
/* Get new text.
WinQuerywindowText
((HWND) mp2,
2`
Buf fer) ;
/* Enable 'Save' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)
default:
return FALSE;
)

/*** Process WM_INITDLG message sent when dialog box first displayed. **
case WM INITDLG:

{:=g=::B:g±:=L::nit ±n edit box to full file path length. */


( hwnd '
ID_SAVEASEDIT,
EM_SETTEXTLIMIT ,
MPFROM2SHORT (PATHLENGTH, 0) ,
0);

• Figure 8.23..
The function Sa:veAsproc of the example program (continued)
DesigningDialogBoxes 379 .

/* Initially disable the 'Save' button until text is entered. */


WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;

/* Obtain current directory path.


Getpath (Filepath, sizeof (Filepath)) ;

/* Format string for 'Current Directory' field.


sprintf (CurDir,"Current Directory: %s",Filepath) ;

/* Display string in 'Current Directory' field.


WinsetwindowText
(WinwindowFromlD (hwnd, ID_SAVEASCD) , /* ID of */
/* 'Current Directory' field. */
CurDir) ; /* String to display. */
return FALSE;

default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

} /i. end Saveasproc */

• Figure 8.23..
The func,tion Sa:veAsproc of the example program (continued)

full file path specification. Note that the message is sent using the func-
tion WinsendDlgltemMsg (Figure 8.25) rather that the usual Win-
SendMsg function. This function allows you to send a message to a
dialog control window that is specified according to its identifier and
the handle of its parent, rather than by its own handle (which is not nor-
mally known). The call to WinsendDlgltemMsg is slightly simpler
than the following equivalent call to WinsendMsg:

Winsenc"sg
(WinwindowFromlD (hwnd, ID SAVEASEDIT) ,
EM SETTEXTLIMIT,
RE=ROM2SHORT (PATHI-ENGTH, 0) ,
0),.

The initialization routine next calls WinEnablewindow to disable the


Save push button, since the edit control initially contains no text. Final-
ly, it writes the current disk drive and directory path specification to the
text control located above the dialog box, identified as ID_SAVEASCD.
As usual, the text is assigned by calling WinsetwindowText. A string
• 380 Programmer's Guide to the os/2Presentation
Manager

containing the current drive and directory is obtained by calling the


utility function Getpath (listed in Figure 7.16 and described in Chap-
ter 7).

The Open Command


The Open command of the File menu allows the user to open a
new file matching a specified file name. The routine that executes this
command is listed in Figure 8.26. This routine simply displays a dialog
box; all of the file-opening logic resides within the dialog procedure.
The dialog procedure for the Open dialog box is named Openproc,
and is listed in Figure 8.27. This function processes the messages shown

EM SETTEXTLIMIT
Purpose..
This message is sent to an edit control of a dialog box to set
the maximum number of characters that can be entered
into the control.

Parameters..
ueJ- mpl
low-order word: The maximum number of characters.
high-order word: 0.
REARAM mp2 NULL.

Return Value ..
The edit control returns TRUE if the function was successful,
or FALSE if an error occurred.

Notes..
This message sets the limit of the number of characters that
can be entered by the user, or assigned to the edit control
through the WinsetwindowText function.

• Figure 8.24..
The EM_SETTEXTHMIT Presentation Manager message
DesigningDialogBoxes 381 .

in Table 8.6. Note that the first values given for mpl in the table repre-
sent the low-order words passed to the dialog procedure in this
parameter, and the second values represent the high-order words. Each
of these messages is now discussed.

WinsendDlgltemMsg
Purpose..
Sends a message to a child control window within a dialog
box; the target control window is specified by its identifier
and the parent window handle (rather than by its own win-
dow handle).

Prototype..
ImESULT APIENTRY WinsendDlgltemMsg
(HWND hwndDlg, A Dialog window handle.
USHORT idltem, Identifier of child control window.
USHORT msg, Message identifier.
REARAM mpl , Message parameter 1 (message-specific
meaning).
REARAM mp2 ) ,. Message parameter 2 (message-specific
meaning).

Return Value ..
The value returned by the control window procedure.

Notes..
This function is equivalent to calling WinsendMsg, specify-
ing the handle of the child control window.

Relate d Functions ..
WinsendMsg (Figure 4.8)

• Figure 8.25..
The WinsendDlglte"Msg Presentation Manager function
• 382 Programmer's Guide to the os/2Presentation
Manager

case ID OPEN: /* 'Open' file menu item.

/* Process message using a dialog box.


WinDlgBox
(HWND DESKTOP /* Handle of parent window: desktop.
hwnd , /* Handle of owner: client.
Openproc, /* Dialog procedure.
NULL, /* Resource module: the .EXE file.
ID OPENDLG, /* Name ID of dialog window: Open.
NULL) ; /* Pointer to procedure data: n/a.
return FALSE;

• Figure 8.26..
The routine for the Open menu command

WM_COMMAND / DID OK
The WM_COMMAND message with the DID_OK command
value is sent when the user selects the Open push button or presses the
Enter key. In response to this message, the dialog procedure first calls
WinQuerywindowText to extract the file name entered into the edit
control. If the file buffer contains unsaved data (which is indicated if the
Modified flag is set to 1), the procedure gives the user the opportunity
to save the current file before reading the new file. Note that rather than
duplicating the code for saving the file, the routine simply sends a
WM_COMMAND message-with an ID_SAVE command code-
directly to the client window; this is exactly the same message that is
sent to the client when the user selects the Save item from the File sub-
menu. (Note also that if the current file has not been assigned a name,
the client window procedure will display the Save As dialog box. It is
thus possible to display a dialog box on top of an already active dialog
box; when the second dialog box is dismissed, the first one is uncovered
and resumes processing.)
Next, the procedure frees the current contents of the heap by calling
ReleaseFile, and reads the new file by calling ReadFile. If the read
operation fails, the program sets FileName to NULL and initializes a
new, empty file by calling NewFile. If the read operation is successful,
the fully qualified version of the new file name is stored in FileName. In
either case, the file name is displayed in the title bar (ShowFileName),
the Modified flag is reset to 0, and the window is initialized for the new
file (Initwindow). Finally, the procedure calls WinDismissDlg to
remove the dialog box.
DesigningDialogBoxes 383 .

• Table 8.6.. Messages Processed by the Openproc_ Dialog Proc€dy

Message mpl Value Action

WM COMRAND DID OK Extracts the file


name, opens the
new file, and dis-
misses the dialog
box
WM COMRAND DID CANCEL Dismisses the
dialog box
WM CONTROL ID OPENEDIT Enables/disables
EN CRANGE the Open button
WM CONTROL ID OPENLIST Changes to the
LN ENTER drive or direc-
tory, or opens the
file selected in
the list box
WM CONTROL ID OPENLIST Writes the name
LN SELECT of the file
selected in the list
box into the edit
field
WM INITDLG Expands the text
linrit of the edit
control; disables
the Open push
button; displays
the initial direc-
tory data in the
dialog box
• 384 Programmer's Guide to the os/2 PresentationManager

MRESULT EXPENTRY Openproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
/*
Processes messages sent to 'Open' dialog box.
*/
(
SHORT Selectlndex; /* Index of selected item in 'Open' list box. */
:E:=±:u:i:= £±E:£ath [pAT££E£:¥£:;ary st;=aE:]€:rfE:=t;ath string. :,
USHORT Reply; /* Response from message box. */

switch (msg)
(
/*** Process WM_COMMAND messages sent by dialog controls. ***************/
case WM COMMAND:

switch (COMMANDMSG(&msg) ->cmd)


(
/*** User clicked on 'Open' button or pressed Enter key. ******/
case DID OK:
/* 5btain text from edit box. */
WinQuerywindowText
(WinwindowFromlD (hwnd, ID OPENEDIT) ,
sizeof (Filepath) ,
Filepath) ;
/* If a file name is entered, try to read the file. */
if (Filepath [0])
(
if (Modified) /* File is modified.
(
/* Warn user and elicit response on
/* saving file.
Reply = WinMessageBox
(HWND DESKTOP,
hwnd '
"File unsaved; Save?",
''PM Text Editor",
0'
MB_YESNO I
MB ICONQUESTION) ;

/* If reply is Yes, send a 'Save' menu */


/* message to client. */
if (Reply == MBID YES)

/* Repeat message until f ile */


/* successfully saved. */
while (Modified)
WinsendMsg
(Hclient,
" COPIAND,
MPFROM2SHORT (ID SAVE, 0) ,
OL);

• Figure 8.27..
The function Oper\Proc of the example program
DesigningDialogBoxes 385 .

} /* end if Modified */
ReleaseFile () ; /* Free current heap.

/* Read the new file.


if (ReadFile (Filepath))
(
/* Warn user if read error occurred.
WinMessageBox
(HWND DESKTOP,
hwnd ,
''Error --Cannot Read File",
''PM Text Editor",
0,
MB OK I
MB-ICONASTERISK) ;

FileName [0] = '\0'; /* Null file name. */


NewFile (); /* New file instead.*/
)
/* File was successfully read.
else
/* Store fully qualified path name.
Qualify (Filepath, FileName) ;
ShowFileName () ; /* Display name in title bar.
Modified = 0; /* Reset modified flag.
Initwindow () ; /* Set window/cursor values.

/* Remove the dialog box. */


WinDismissDlg
(hwnd, /* Handle of dialog window. */
TRUE) ; /* Code returned by WinDlgBox. */
return FALSE;

return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:

/* Remove the dialog box. */


WinDismissDlg
( hwnd , /* Handle of dialog window. */
TRUE) ; /* Code returned by WinDlgBox. */
return FALSE
default:
ret.urn FALSE;
)

/*** Process WM CONTROL messages sent by edit box or list box. **********/
case WM CONTROL:

• Figure 8„27..
The function Openproc of the example program (continued)
• 386 Programmer's Guide to the os/2 Presentation Manager

switch (SHORTIFROMMP (mpl) )


(
/*** Message sent by edit box. ********************************/
case ID OPENEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:
/*-Get the new text. */
WinQuerywindowText
((HIND) mp2,
2,
Buf fer) ;
/* Enable 'Open' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

/*** Message sent by list box. ********************************/


case ID OPENLIST:
/*-Get index of selected item. */
Selectlndex = (SHORT) WinsendDlgltemMsg
( hwnd ,
ID OPENLIST,
"-QUERYSELECTION,
OL'
OL);
/* Get text belonging to selected item.
WinsendDlgltemMsg
( hwnd ,
ID OPENLIST,
I"-QUERYITEMTEXT,
MPFROM2SHORT (Selectlndex, sizeof (Buffer) ) ,
MPFROMP (Buffer) ) ;

/* Branch on code for specific event.


switch (SHORT2FROMMP (mpl) )
(
/* User pressed Enter key or double clicked.
case LN ENTER:
/*-Item is for a drive letter.
if (Buffer [0] == '[' &&
Buffer [1] == I-')
(
/* Change to specified drive.
DosselectDisk (Buffer [2] -64) ;
/* Update dialog box data.
InitDlg (hwnd) ;
)
/* Item is for a directory.

• Figure 8.27..
The function Openproc of the example program (continued)
DesigningDialogBoxes 387 .

else if (Buffer [0] == '[')


(
/* Null terminate after directory.
Buffer [strlen (Buffer) -1] = '\0';
/* Change to new directory.
DoschDir
(Buffer + 1,
OL);
/* Update dialog box data.
InitDlg (hwnd) ;
)
/* Item is a file name.
else if (Buffer [0])
(
/* Save the file by sending message. */
WinsendMsg
(hwnd, /* Dialog window hand.*/
#F:8#3kT (D!: g2::??e ID. */
OL);

/* Remove the dialog box. */


WinDismissDlg (hwnd, TRUE) ;
return FALSE;
)
return FALSE;

/* New item is selected (highlighted). */


case LN SELECT:
/*-Null string for drive or directory. */
if (Buffer [0] == '[')
Buffer [0] = '\0';
/* Place selected text in edit box. */
WinsetwindowText
(WinwindowFromlD (hwnd,ID OPENEDIT) ,
Buf fer) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;
)

/*** Process WM_INITDLG message sent when dialog box first displayed. ***/
case WM INITDLG:

¢:ng=::E:g::=k::nit ±n edit box to full file path length. */


( hwnd ,
ID OPENEDIT,
EM-SETTEXTLIMIT ,

• Figure 8.2'.7:
The function Oper\Proc of the example program (continued)
• 388 Programmer's Guide to the os/2 PresentationManager

MPFROM2SHORT (PATHLENGTH, 0) ,
0);

/* Initially disable the 'Open' button until text is entered. */


WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;

/* Display initial directory and list box data. */


InitDlg (hwnd) ;

return FALSE;

default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;

) /* end switch */
} /* end Openproc */

• Figure 8.27..
The function Oper\Proc of the example program (continued)

WM COMMAND/DID CANCEL
In response to the Cancel command, the dialog procedure simply
calls WinDismissDlg to dismiss the dialog box.

W.h4 CONTROL / ID OPENEDIT / EN CI-IANGE


As described in previous sections, this WM_CONTROL command
is sent whenever the text in the edit control is modified. The dialog pro-
cedure enables the Open push button if this edit contains at least one
character, and disables it if the edit text is NULL.

WM CONTROL/ID OPENLIST/ LN ENTER


Before processing this WM_CONTROL command, or the one
described in the following section, the dialog procedure obtains the text
for the currently selected item within the list box (the selected item is
the one that is highlighted). To obtain the text for the selected item, the
procedure cannot simply call WinQuerywindowText. Rather, it sends
two specific messages directly to the list box control (note that these
DesigningDialogBoxes 389 .

messages are sent using the WinsendDlgltemMsg function, described


previously in the chapter). First, it sends the LM_QUERYSELECTION
message (Figure 8.28) to obtain the index of the selected item within the
list box; it then sends the LM_QUERYITEMTEXT message (Figure 8.29)
to obtain the text for the item corresponding to this index (the text is
copied into Buffer).
The list box sends a WM_CONTROL message with the LN_ENTER
code if the user presses the Enter key while an item in the list is high-
lighted, or if the user double-clicks on an item with the mouse. Note
that the selected list box item can be a disk drive letter (which begins
with the characters ``[-"), a directory specification (which begins with
the '[' character), or a file name (you will see later how these different
types of items are formatted). If the current selection contains a disk
drive letter, the procedure first changes to the specified drive by calling
the DosselectDisk OS/2 function, and then calls the function InitDlg
to update the dialog box control that displays the current directory, and

LM_QUERYSELECTION
Purpose..
This message is sent to a list box control window to obtain
the index of the currently selected item.

Parameters..
REARAM mpl 0.
rmARAM mp2 0.

Return Value ..
The index of the selected item.

Notes..
You can obtain the text for the selected item by sending the
LM_QUERYITEMTEXT message (Figure 8.29).

• Figure 8.28..
The LM_QUER:Y SELECTION Presentation Manager message
• 390 Programmer's Guide to the os/2PresentationManager

LM_QUERYITEMTEXT
Purpose..
This message is sent to a list box control window to obtain
the text for a specific item within the list box.

Parameters..
ueJ- mpl
low-order word: The index of the item.
high-order word: The length of the receiving buffer.
REARAM mp2 The far address of the receiving buffer.

Return Value ..
The actual length of the item text.

Notes..
You can obtain the index of the item that is currently selected by
sending the LM_QUERYSELECTION message (Figure 8.28).

• Figure 8.29..
The LM_QUEKYITEMTEXT Presentation Manager message

to update the contents of the list box (InitDlg is explained later, in the
section on the WM_INITDLG message). Likewise, if the current selec-
tion contains a directory specification, the procedure calls the OS/2
function DoschDir to change to the new directory, and then calls Init-
Dlg to update the dialog box data.
Finally, if the selected item is a file name, the procedure sends itself a
WM_COMMAND message with a DID_OK command code to cause it
to save the file under the selected name. (You may have noticed that the
LN ENTER routine obtains the file name from the list box, while the
DID_OK routine obtains the file name from the edit control. It might
seem, therefore, that when sending this recursive message, the DID_OK
routine would not access the correct file name. Note, however, that the
LN_SELECT message, described next, is always sent bc/ore the
LN_ENTER message; and, as you will see, the LN_SELECT message
copies the selected text from the list box to the edit control.)
DesigningDialogBoxes 391 .

WM CONTROL/ID OPENLIST/ LN SELECT


The list box sends a WM_CONTROL message with the
LN SELECT code whenever a new list box item is selected. An item can
bes-electedbyclickingonitwiththemouse(whichhighlightstheitem),
or by moving the highlight bar to the item using the arrow keys (to use
the arrow keys, the list box must own the keyboard focus; the user can
move the focus from one control to another with the Tab key). The
dialog procedure responds to this message by calling Winsetwindow-
Text to copy the selected text to the edit control.

WM INITDLG
The initialization routine invoked through the WM_INITDLG
message first sends the EM_SETTEXTLIMIT message to the edit control
to expand its text limit to accommodate a full path specification. Next,
it calls WinEnablewindow to initially disable the Open push button,
and finally, it calls InitDlg (Figure 8.30) to display the required data for
the current drive and directory.
The InitDlg function is called when the dialog box is initialized, and
whenever the current drive or directory changes. It performs the fol-
lowing sequence of tasks:

1. It obtains a string containing the current drive letter and direc-


tory specification by calling Getpath, and displays this string in
the text control that shows the current directory path
(ID_OPENID).
2. InitDlg then sends a LM_DELETEALLmessage (Figure 8.31) to
the list box, which causes this control to clear all items that it
contains.
3. The function calls the os/2 service DosQCurDisk to obtain a
mapping of all installed disk drives. It then adds the letter of
each drive to the set of items displayed in the list box. An item is
inserted into the list box by sending the LM_INSERTITEM mes-
sage (Figure 8.32). Disk drive letters are surrounded by the char-
acters ``[-'' and ``-]" to distinguish them from directory and file
names; for example, drive A is displayed as ``[-A-]''. Note that
• 392 Programmer's Guide to the os/2PresentationManager

VOID InitDlg (HWND hwnd)


/*
Called by 'Openproc' to display current data in 'Current Directory' field
and list box of 'Open' dialog box.
*/
(
register int Drive; /* Disk drive letter.
USHORT DriveNumber; /* Disk drive number.
ULONG LogicalDrives; /* Mapping of installed drives.
char Buffer [PATHLENGTH] ; /* Holds file paths.
HDIR Hsearch = 1; /* OS/2 file search handle.
FILEFINDBUF FindBuf ; /* Structure for file searches.
USHORT Filecount = 1; /* Count files to find/found.
char *Ptrch; /* Temporary character pointer.
/*** Obtain current default drive path. **************************************/
Getpath (Buffer, sizeof (Buffer)) ;

/*** Display current drive and directory path in 'Current Directory' field. **/
WinsetwindowText
(WinwindowFromlD (hwnd, ID OPENCD), /* ID of 'Current
/* Directory' field
Buf fer) ; /* Buffer containing text to display.
/*** Obtain current default disk and mapping of installed drives. ************/
DosQCurDisk
( & Dr iveNumber , /* Receives number of current drive. */
&LogicalDrives) ; /* Receives mapping of installed drives. */
/*** Clear all existing entries from the list box. ***************************/
*/
WinsendDlgltemMsg /* Send message to dialog item.
( hwnd ' /* Handle of dialog window. */
ID OPENLIST, /* ID of list box. */
LM-DELETEALL, /* Delete all entries. */
0, /* mpl: not used. */
0); /* mp2: not used. */

/*** Insert drive letters into list box. *************************************/


for (Drive = 'A'; Drive <= 'Z'; ++Drive)
(
if (LogicalDrives & 1)
(
sprintf (Buffer,"[-%c-]",Drive) ;
WinsendDlgltemMsg /* Send message to dialog item.
(hwnd, /* Handle of dialog window.
ID OPENLIST, /* ID of list box.
IiM-INSERTITEM, /* Insert an item.
MPFROM2SHORT (LIT SORTASCENDING, 0) , /* Ascending sort
/k Or=ile:I.
MPFROMP (Buffer)) ; /* Address of item text.
)
LogicalDrives >>= 1;
)

/*** Insert directories and files into list box. *****************************/

• Figure 8.30..
The function lr\itDL8 of the example program
DesigningDialogBoxes 393 .

/* Find first directory or file. */


DosFindFirst

i:i:i:;;;::dBuf, , ;; i;:;:¥:;:::::=::i;::e±::;::::i:nrf:::on;;
/* Process each matching file. */
while (Filecount)
* If match is a directory, but NOT '.', insert it in list box. */
f (FindBuf .attrFile & OxOO10 &&
!(FindBuf.achName [0] == I.I && FindBuf.achName [1] == '\0'))
(
sprintf (Buffer,"[%s]",FindBuf.achName) ;
WinsendDlgltemMsg /* See above. */
( hwnd '
ID OPENLIST,
"-INSERTITEM
MPFROM2SHORT (LIT SORTASCENDING, 0) ,
MPFROMP (Buffer) )T
)
/* If match is a normal file, insert only if it has the .TXT or
/* .C extension.
else if (strcmp ((Ptrch = Extension (FindBuf.achName)) ,"TXT") == 0
I I strcmp (Ptrch,"C") == 0)
WinsendDlgltemMsg /* See above.
( hwnd ,
ID OPENLIST,
IIM-INSERTITEM,
MPFROM2SHORT (LIT SORTASCENDING, 0) ,
MPFROMP (FindBuf .achName) ) ;

/* Find NEXT matching file.


*/
DosFindNext
(Hsearch, /* Search handle returned by DosFindFirst.*/
&FindBuf, /* Receives information on matching file. */
sizeof (FindBuf) /* Length of receiving buffer. */
&Filecount) ; /* Returns number of matching files left. */
)

) /* end InitDlg */

• Figure 8.30..
The function mrhiD\g of the example program (continued)
• 394 Programmer's Guide to the os/2 Presentation Manager

this message is accompanied by a code indicating that the items


should be sorted in ascending order.
4. It then uses the os/2 functions DosFindFirst and DosFindNext
to obtain the name of each directory and each file within the cur-
rent directory. Directory names are formatted with surrounding
brackets (for example, the directory CODE would be formatted
as ``[CODE]''). All directory names (except ``.'') and all files that
have the .C or .TXT extension are inserted into the list box.

Note that selecting only files with the .C or .TXT extension is an ar-
bitrary feature. You could, of course, alter this function to display ¢JJ
files, or files selected according to another criterion (or allow the user to
specify the criterion).

LM DELETEALL
Purpose..
This message is sent to a list box control window to delete all
items in the list box.

Parameters..
MPARAM mpl 0.
mARAM mp2 0.

Return Value ..
TRUE if the operation was successful, or FALSE if an error
occurred.

• Figure 8.31..
The LM_DELETEALLL Presentation Manager message
DesigningDialogBoxes 395 .

LM INSERTITEM
Purpose..
This message is sent to a list box control window to cause it
to add an item to the list.

Parameters..
REJ- "pl
low-order word: One of the following flags, indicating
where the item is to be inserted:

Flag Position
LIT END At end of list
LIT SORTASCEND- In ascending order
ING-
LIT SORTDESCEND- In descending order
ING_

high-order word: 0.
REARAM "p2 The far address of buffer containing
the text for the item.

Return Value..
The index of the inserted item, or one of the following error
codes if the function is unsuccessful:

Code Meaning
LIT MEMERROR The list box does not have
sufficient memory to allocate
space for the item.
LIT ERROR AIl other errors.

• Figure 8.32..
The LM_INSERTITEM Presentation Manager message
• 396 Programmer's Guide to the os/2 Presentation Manager

• CONCLUSION
Listed at the end of this chapter is the complete set of files required
to prepare the current version of the example program. The following
files are provided:

Figure File

8.33 A MAKE file for preparing the example program


8.34 The linker definition file
8.35 The dialog resource script
8.36 The general resource script
8.37 The header file containing definitions for the presenta-
tion Manager resources
8.38 The c source code file

The linker definition file of Figure 8.34 is the same as those provided
for previous versions of the example program, except that each of the
dialog procedures is listed under the EXPORTS statement. Note that
the dialog resource script of Figure 8.35 is generated directly by the
Dialog Box Editor; this file is included by the general resource script
file of Figure 8.36. The resource script of Figure 8.36 is processed by the
resource compiler, and is the same as the script file described in Chap-
ter 7 except for the statement that includes the dialog resource script.
The header file of Figure 8.37 is included both in the resource script
(Figure 8.36) and in the C source file (Figure 8.38).
This chapter concludes the treatment of basic Presentation Manager
features. The version of the example text editor program given here is
the last complete listing of this application provided in the book. The
remaining chapters discuss more advanced Presentation Manager fea-
tures, and offer suggestions for incorporating these features into the
current version of the example program. The example listings given in
subsequent chapters consist of short programs and program fragments.
You can, however, add these features to the example program listed in
this chapter both to increase the usefulness of this application and as an
exercise in Presentation Manager programming.
DesigningDialogBoxes 397 .

I :i!:r=A&i3=iie prepares the program of Figure 8.38. The following


# are involved:

i ;I§§:;;±§iFIG836RES
#
FIG8 38.OBT : FIG8 38.C FIG8 37.H
ct iw2± ic i7;+ ic;%Ns FTif riR>_38.c

FIG8 38.EXE : FIG8 35.DLG FIG8 36.RC FIG8 37.H


rc /r FIGS 36TRC

FIG8 38.EXE : FIG8 38.OEU FIG8 34.DEF FIG8 36.RES


link /NOD FIG5 38.OEL,, NU-L.LST, OS2.IIB SLIBCE.LIB, FIG8_34.DEF
rc FIGS 36.RES-FIG8 38.EXE

• Figure 8.33..
A MAK:1E file for preparing the example program

Figure 8.34
definition file for the program of Figure 8.38
FIGS 38

1024
8192
Wndproc
Openproc
Saveasproc
Aboutproc
Findproc
Gotoproc

• Figure 8.34..
The linker defroition file for the example program
• 398 Programmer's Guide to the os/2 Presentation Manager

/*
Figure 8.35

Dialog resource script for the program of Figure 8.38.


*/
DLGTEMpliATE 257 LOADONCALL MOVEABLE DISCARDABLE
BEGIN
DIALOG "'J 2:Sic::is:Sir:88, ]7£5 :£v¥3:¥:EALIGN I FS_DLGBORDER I

BEGIN
CONTROL "Save File As:", -1, 3, 50, 63, 8, WC STATIC,
SS_TEXT I DT_LEFT I DT_TOP I WS_GROUP-I WS_VISIBLE
CONTROL "", 257, 5, 31,170, 13, WC_ENTRYFIELD, ES_LEFT I ES_AUTOSCROLL
ES_MARGIN I WS_TABSTOP I WS_VISIBLE
CONTROL ''Current Directory:", 258, 3, 61,174,11, WC_STATIC, SS_TEXT I
DT_LEFT I DT_TOP I WS_GROUP I WS_VISIBLE
CONTROL "Esc=Cancel", 2, 99, 7, 56, 16, WC_BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CoNTROL Wsaven, 1, 25, 8, 53, 14, WC_BUTTON, BS_PUSHBUTTON I BS DEFAULT
WS_TABSTOP I WS VISIBLE
END
END

DLGTEMpliATE 258 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "", 258, 71, 43, 182, 53, FS_NOBYTEALIGN I FS_DLGBORDER I
WS_CLIPSIBLINGS I WS SAVEBITS
BEGIN
CONTROL "", 258, 37, 35, 141, 10, WC ENTRYFIELD, ES_LEFT I
ES_AUTOSCROLL I ES_MARGIN I ffs_TABSTOP I WS VISIBLE
CONTROL "Esc=Cancel", 2, 105, 9, 60, 13, WC_BUTTON, BS_PUSHBUTTON i
WS VISIBLE
CONTROL "Flnd", 1, 21, 9, 53, 13, WC_BUTTON, BS_PUSHBUTTON I BS DEFAULT
WS_TABSTOP I WS_VISIBLE
CONTROL "Find:", -1, 6, 35, 23, 9, WC_STATIC, SS_TEXT I DT_LEFT I
DT_TOP I WS_GROUP I WS VISIBLE
END
END

DLGTEMPIIATE 259 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIALOG "", 259, 90, 51, 147, 52, FS_NOBYTEALIGN I FS_DLGBORDER I
WS_CLIPSIBLINGS I WS_SAVEBITS
BEGIN
CONTROL ''Go to Line Number:", -1, 3, 33, 86,10, WC STATIC,
SS_TEXT I DT_LEFT I DT_TOP I WS_GROUP I WS VISIBLE
CONTROL "", 259, 96, `35, 45, 7, WC ENTRYFIELD, ES_IEFT I ES_AUTOSCROLL
ES_MARGIN I WS_TABSTOP I WB VISIBLE
CONTROL "Esc=Cancel", 2, 77, 11, 61T 14, WC_BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CONTROL "G6 to Line", 1, 9, 12, 52, 12, WC_BUTTON, BS_PUSHBUTTON I
BS_DEFAULT I WS_TABSTOP I WS_VISIBLE
END
END

• Figure 8.35..
The dialog resource script for the example progran
DesigningDialogBoxes 399 .

DLGTEMPILATE 260 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIA]uOG Mw, 260, 74, 17, 153, 123, Fs_NOByTEALIGN I Fs_DroBORDER I
WS CLIPSIBLINGS I WS_SAVEBITS
BEG]:N
CONTROL "Open File Name:", -1, 3,108, 78,10, WC STATIC,
SS TEXT I DT_LEFT I DT_TOP I WS_GROUP I W5_VISIBLE
CONTROL "'T 260, 5, 93, 132,11, WC_ENTRYFIELD, ES_LEFT I ES_AUTOSCROLL
ES MARGIN I WS_TABSTOP I WS_VISIBLE
CONTROL ""T 261, 3, 67,137, 8, WC_STATIC, SS_TEXT I DT_LEFT I
DT TOP I WS_GROUP I WS_VISIBLE
CONTROL ""T 262, 5, 6, 82, 57, WC_LISTBOX, WS_TABSTOP I WS VISIBLE
CONTROL "Open",1, 95, 41, 57,13, WC_BUTTON, BS_PUSHBUTTOR I BS_DEFAULT
WS TABSTOP I WS_VISIBLE
CONTROL "E=c=Cancel", 2, 93, 12, 59, 16, WC_BUTTON, BS_PUSHBUTTON I
WS VISIBLE
CONTROL "CIrrent Directory:", -1, 3, 79, 76, 9, WC_STATIC, SS_TEXT I
DT LEFT I DT_TOP I WS_GROUP I WS_VISIBLE
END
END

DLGTEMP]IATE 256 LOADONCALL MOVEABLE DISCARDABLE


BEGIN
DIA].joG "", 256,108, 32,114, 85, FS NOBYTEALIGN I FS_DLGBORDER I
WS CLIPSIBLINGS I WS_SAVEBITS
BEG:[N
CONTROL ''Presentation Manager", -1, 2, 67,110, 9, WC_STATIC,
SS TEXT I DT_CENTER I DT_TOP I WS_GROUP I WS VISIBLE
CONTROL "TExt Editor", -1, 2, 54,109, 9, WC_STATIC,-SS_TEXT I
DT CENTER I DT_TOP I WS_GROUP I WS_VISIBLE
CONTROL "VErsion 1.0", -1, 3, 40,109, 9, WC STATIC, SS_TEXT I
DT CENTER I DT_TOP I WS GROUP I WS_VISIBLE
CONTROL "OR",1, 39,15, 34,12T WC_BUTTON, BS_PUSHBUTTON I BS_DEFAULT I
WS GROUP I WS TABSTOP I WS_VISIBLE
END
END

• Figure 8.35o.
Tire dialog resource script for the example program (continued)
• 400 Programmer's Guide to the os/2 Presentation Manager

Figure 8.36

Resource script for the program of Figure 8.38


*/

#include <OS2.H>
#include "FIG8 37.H"

MENU ID FRAME RESOURCE


BEGIN
SUBMENU " ~File" , ID FILE
BEGIN
MENUITEM "~New", ID NEW
MENUITEM "~Open...\tF3", ID_OPEN
MENUITEM "~Save\t^S F2", ID_SAVE
MENUITEM ''Save ~As...", ID-SAVEAS
MENUITEM "~Print\t^P F4" ID_PRINT
MENUITEM SEPARATOR
MENUITEM "~Exit", ID EXIT
MENUITEM "A-bout...", ID-ABOUT
END
„ -Edit" , ID EDIT
" Cu -t\tsh i ft+Del " , ID CUT
" ~ Copy\tctrl+Ins " , ID_CoPY
" ~ Paste\tshi ft+Ins " ID-PASTE
" ~ Search" , ID SEARCH

" -F'ind . . . \t ` F" ' ID FIND


MENUITEM ''Find -Next\t^N", ID-FINDNEXT
MENUITEM ''~Go to Line...\t^G", ID-GOTOLINE
END
SUBMENU " ~Options" , ID OPTIONS
BEGIN
MENUITEM ''Overwrite Mode\tlns", ID INSERT
END
MENUITEM "F1=Help" , ID HELP,
Mlg_HELP I MIS BUTTONSEPARATOR
END

VIRTUALKEY
VIRTUALKEY
VIRTUALKEY
VIRTUALKEY , SHIFT

rcinclude FIGS 35.DljG

• Figure 8.36..
The general resource script for the exanple progran
DesigningDialogBoxes 401 .

Figure 8.37

Header file to be included in the resource file of Figure 8.36 and the
C source file of Figure 8.38
*/

#def ine ID FRAME RESOURCE

#def ine ID FILE


#def ine ID~NEW
#def ine ID~OPEN
#def ine' ID-SAVE
#def inei I:D-SAVEAS
#def in€t ID~PRINT
#def ine. ID~EXIT
#def in€i ID-ABOUT

#def ine ID EDIT


#def ine ID-CUT
#def ine ID-COPY
#def ine ID-PASTE

#def ine ID SEARCH


#def ine ID-FIND
#def ine ID-FINDNEXT
#def ine ID~GOTOLINE

#def ine ID OPTIONS


#def ine ID-INSERT

#def ine ID HELP

#def ine ID ABOUTDLG

#def ine ID SAVEASDLG


#def ine, ID~SAVEASEDIT
#def ine ID-SAVEASCD

#def ine ID FINDDLG


#def ine ID~FINDEDIT

#def ine ID GOTODLG


#def ine ID-GOTOEDIT

#def ine ID OPENDLG


#def ine ID-OPENEDIT
#def ine ID-OPENCD
#def ine ID-OPENLIST

• Figure 8.37..
The header containing definitions for the example program resources
• 402 Programmer's Guide to the os/2PresentationManager

Figure 8.38

Version 5 of the Presentation Manager text editor example program.


This version adds the following features:
o A Presentation Manager menu for selecting commands
o Accelerator keys for rapidly accessing frequently used menu items
o Dialog boxes for interacting with the user for certain menu items
o An ''About" dialog box
o Commands for managing file I/0:
o opening a new f ile
o reading an existing f ile
o saving the file being edited, under its original name
o saving the f ile under a new name
o A command for searching for a string within the f ile
o A command for moving the cursor to a specific line within the f ile
o A menu command for toggling between overwrite and insert modes
*/

#def ine INCL GPI /* Include all Gpi... function declarations. */


#def ine INCL-WIN /* Include all Win... function declarations. */
#include <OSZ.H>
#include <STDIO.H> /* C library header files:
#include <PROCESS.H>
#include <IO.H>
#include <STRING.H>
#include <STDLIB.H>

#include ''FIG8 37.H" /* Definitions shared with resource script. */


/*** Window procedure declaration. *******************************************/

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

/*** Declarations / definitions for file-and buffer-management module. ******/


#def ine LINEBUFSIZ /* Size of buffer for holding lines.
#def ine ERROPEN /* Error: opening file.
#def ine ERRTOOBIG /* Error: file too large.
#def ine ERRMAXLINES /* Error: maximum file lines exceeded.
#def ine ERRALLOC /* Error: heap allocation.
void Buflnit (void) ; /* Initializes buffer-management module.
/* Deletes character from buffer:
int Deletechar (SHORT Line, SHORT Column) ;
void DeleteLine (SHORT Line) ; /* Deletes the current line.
S::rG::::::X:::a?:nt±E:n:r?°rNumber/i Get: :::=::: :=r::n:e::a%:f::=ing.
3::3TG::±::::::n7::tt±::er;ne, ; ,: 8:t:i::n:tEe:5O:±=; i:n:u£::=;r.
/* Inserts character into buffer:
int Insertchar (SHORT Line,USHORT Character,SHORT Column, int Overwrite)

• Figure 8.38..
The C source code file for the example program
DesigningDialogBoxes 403 .

/* Inserts new line into buffer.


void lnsertLine (SHORT Line, SHORT Column) ;

i;::;::i:::::i:::::::;;;i;:;;; , #:i:;;::;::¥::¥:::;;:i:;:i:e
int SearchBuf (char *Findstring, PSHORT Line, PSHORT Col); /* Find string

int Last.Line = -1; /* Number of last line in buffer.


HHEAP HHeap = NULL; /* PM heap handle.

/*** Utility function declarations. ******************************************/

void ErrorQuit (char *Message) ; /* Print error message, end program.


char *Extension (char *FileName) ; /* Returns pointer to file extension.
void Getpath (char *Path, unsigned PathLength) ; /* Obtains directory path.
void Initwindow (void) ; /* Sets parameters for a new file.
void Qualify (char *Unqual, char *Qual) ;/* Fully qualifies a file path name.

¥±! :i;I::!±:I;:i:i:i:;i|;1) ; ;; i;::i:::i::I: ::::::::::i¥m:i|e name.


/*** Global definitions / variables. *****************************************/
*/
#def ine PATHLENGTH 128 /* Maximum length of file path.
HWND IiFrame; /* Handle to main frame window.
HWND HMenu; /* Handle to menu window.
HAB HAncBlk; /* Handle to anchor block.
HMQ HMesQue; /* Message queue handle.
char Message [64] ; /* Buffer for displaying error messages.
char F'ileName [PATHLENGTH] ; /* Name of current file.
char Title [25] = "''; /* Text for title bar.
unsigned char Modified = 0; /* Flag indicating whether file modified.
HWND r3Client; /* Handle to main client window.

void main (int argc, char *argv[])


int ReadError = 0; /* Error occurred reading file.
QMSG QueMess; /* Message structure.
ULONG CtlData = /* Control windows to include.
FCF HORZSCROLL /* Horizontal scroll bar.
FCF-MENU /* Menu.
FCF-MINMAX /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR /* Title bar.
FCF-VERTSCROLL; /* Vertical scroll bar.
Buflnit () ; /* Initialize buffer module.

• Figure 8.38..
The C source code file for the example program (continued)
®404 Programmer's Guide to the OS/2 Presentation Manager

/*** If no file name given, set 'FileName' to NULL and open new file. ********/
if (argc < 2)
(
FileName [0] = '\0';
NewFile ();
)
/*** If file name given, save fully qualified name and read file. ************/
else
(
Qualify (argv [1],FileName) ;
ReadError = ReadFile (FileName) ;
)

HAncBlk = Winlnitialize (0) ; /* Initialize PM system for process. */


HMesQue = WincreateMsgQueue (HAncBlk,O) ; /* Create a message queue.

WinRegisterclass /* Register procedure for main window.


(HAncBlk,
''mlN„ , /* Anchor block handle.
/* Window class name.
Wndproc , /* Window procedure associated w/ class.
OL' /* Class style.
0); /* Extra storage bytes.
HFrame = Wincreatestdwindow /* Create parent window.
(HWND DESKTOP, /* Parent window handle.
FS_ACEELTABLE I /* Install accelerator table.
WS VISIBLE, /* Frame window style.
&cEIData' /* Address of control data.
''RAIN„ ,
/* Client window class name.
Title, /* Text for title bar.
OL, /* Client window style.
0' /* Resource module handle.
ID FRAME RESOURCE, /* Resource identification.
&H5lientT; /* Address to receive client window hand.
if (HFrame == NULL)
ErrorQuit ("Wincreatestdwindow") ;
ShowFileName () ; /* Display file name in window title.
HMenu = WinwindowFromlD /* Get handle of menu window.
(HFrame, /* Handle of parent frame window.
FID MENU) ; /* ID of menu child window.

if (ReadError) /* Quit if read error.


ErrorQuit (ErrorMessage (ReadError) ) ;
WinsetFocus /* Give focus to client window.
(HWND DESKTOP, /* Handle for desktop window.
HclieHt) ; /* Client window handle.
while (WinGetMsg /* Get messages until WM QUIT.
(HAncBlk, /* Anchor block handle.

• Figure 8.38..
The C source code file for the exanple program (continued)
Designing Dialog Boxes 405.

&QueMess , /* Address of message structure.


0, /* Window filter.
0' /* First message identifier.
0)) /* Last message identifier.
WinDispatchMsg (HAncBlk,&QueMess) ; /* Dispatch messages.

Quit (0); /* Normal termination.

) /* end main */

/*** Window procedure and subroutines. ******************„*******************/


EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Command (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Help (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY HScroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY InitMenu (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY SetFocus (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY VirtKey (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM
EXPENTRY Vscroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM

/*** Di.aLoq procedures. ***H"****H*****H**H*******""****"*****"******/


MRESULT EXPENTRY Openproc (HWND
MRESULT. EXPENTRY Saveasproc (HWND
MRESULT EXPENTRY Aboutproc (HWND
MRESULT EXPENTRY Findproc (HWND
MRESULT EXPENTRY Gotoproc (HWND

void N(>tYet (char *Message) ; /* Displays 'not implemented' message.

static SHORT xchar; /* Character width.


static SHORT ycharTot ; /* Total height of characters.
static SIIORT ycharDesc; /* Height of character descenders.
static SIIORT xwin; /* Horizontal size of window.
static SIIORT ywin; /* Vertical size of window.
static HWND HVscroll; /* Handle to vertical scroll bar window.
_, __ _1 _

static HWND HHScroll; /* Handle to horizontal scroll bar window.


static int Firstcol; /* Character to be in first column position.
static int FirstcolMax; /* Maximum value of 'Firstcol' .
static SHORT TopLine = 0; /* Number of top line in window.
static s]IORT TopLineMax; /* Maximum value of 'TopLine'.
static FATTRS FontAttributes; /* Stores font attributes from GpiQueryFonts
********************************************/
/*** Cursor-management variables
static SHORT CursorLine = 0;
static SHORT Cursorcol = 0;
static SHORT LastcursorLine = 0; ;: :::::::n:::::::::::::o:::::::::;r. :;
/*** F-.Lag for insert mode. ***********"H*************************"*H******/

• Figure 8.38..
Tire C source code file for the example program (continued)
• 406 Programmer's Guide tothe os/2Presentation
Manager

i:::i: i:: i:i:¥::k:ao= 0; ;; ;::§'f§::i::i:: I:::£;::d[;a:n::::.mode.


static char Findstring [33] = {'\0'}; /* Holds the search string.
#define ID COURIER 99L /* Local font ID.

MRESULT EXPENTRY Wndproc


(HWND hwnd, /* Window handle. */
USHORT msg, /* The message. */
MPARAM mpl, /* Message-specific information. */
MPAEN mp2) /* Message-specific information. */
(
switch (msg)
(
Case vy¥ ,C,TAR_: /* Message sent when keyboard key is received. */
/*-Key was rele'ased .----- I---~ ---- `
if (CHARMSG (&msg)->fs & KC KEYUP)
return FALSE;

/* Valid character key.


else if (CHARMSG (&msg)->fs & KC CHAR)
return Character (hwnd, msgT mpl, mp2) ;

/* Valid virtual key code.


else if (CHARMSG (&msg)->fs & KC VIRTUALKEY)
return VirtKey (hwnd, msg, ripl, mp2) ;

/* Invalid key: neither virtual nor character.


else
return FALSE;

/*** Process WM_COMMAND message sent when user selects a menu item. *****/
case WM COMMAND:
return Command (hwnd, msg, mpl, mp2) ;

case WM CREATE: /* Message sent when window is first created. */


return Create (hwnd, msg, mpl, mp2) ;

/*** Process WM_HELP message sent when user selects help or presses F1. */
case WM HELP:
return Help (hwnd, msg, mpl, mp2) ;
case WM HSCROLL: /* Message sent on horizontal scroll activity. */
return HScroll (hwnd, msg, mpl, mp2) ;

/*** Process WM_INITMENU message sent when menu item is first selected. */
case WM INITMENU:
return InitMenu (hwnd, msg, mpl, mp2) ;
case WM PAINT: /* Message sent when window data is invalid. */

• Figure 8.38..
The C source code file for the example program (continued)
Designing Dialog Boxes 407.

return Paint (hwnd, msg, mpl, mp2);

case WM SETFOCUS: /* Message sent when client focus changes. */


return SetFocus (hwnd, msg, mpl, mp2) ;

case WM SIZE: /* Message sent whenever window changes size. */


return Size (hwnd, msg, mpl, mp2);

case WM VSCROLL: /* Message sent on vertical scroll activity. */


ref-urn Vscroll (hwnd, msg, mpl, mp2) ;

default: /* Perform default processing on all other messages. */


return WinDefwindowproc (hwnd,msg,mpl,mp2) ;

} /* end switch */

} /* end Wndproc */

/*** Subroutines called by window procedure. *********************************/

MRESULT EXPENTRY Character (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

::g±:t;:c:?t col; /: ::::sf::o::::a::sg::e=:::a:::e:haracters. :/


/*** Set global 'Modified' flag. *********************************************/
Modified = 1;

if (LastcursorLine != CursorLine) /* Adjust buffer for new cursor */


*/
( /* line.
ReleaseTempBuf (LastcursorLine)
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
if (CiARESG(&msg)->chr == '\b') /* Process a backspace key.

if (Cursorcol == 0) /* Cursor at first column.


if (CursorLine == 0) /* Cursor in first line.
return TRUE;

w|nse¥;::!i::E8::(5:_¥:=i:?:;:;:¥:=::;::::;::;::;:;:;:

wLnse#5::§£§E8R:t5:_¥±R{:3:;:i:::;::::;;:::i:i;;;:g=ey

if (!Insert) /* In overwrite mode, task finished. */

• Figure 8.38..
Tire C source code file for the example program (continued)
• 408 Programmer's Guide to the os/2Presentation
Manager

return TRUE;
if (!.oinLine (CursorLine + 1)) /* Join lines. */
(
WinAlarm (HWND DESKTOP, WA ERROR) ;
return TRUE;
)

LastcursorLine = CursorLine;
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
WinsendMsg /* Send message to vertical scroll bar.
(HVscroll, /* Recipient handle.
£BfEgE:?:53!L?3:;Line, o, , /* Se;*p3::::::n: range.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

W±nEn:£t:¥::::T ,: E:::::e::Lxa:::::i P°SS±bLe.


TopLineMax ? 1 : 0); /* Enable only if max. != 0.

E::t:XE:::t--o,xwin, /* calculate invalid rectangle. */


Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;

wLn|n|i:§§;;eRe;::::i::;*!::i:;i::i::i:::;::::::;;:;;iDREN;;

Winupdatewindow (hwnd) ; /* Force window update. */


return TRUE;

) /* end cursor at column 0 */


Winse?:#:g, /: ::::n:e::I:::Oxa::::?ge t° Self.
WM CHAR, /* Character received message.

#:EE8¥2§EBE: tg:_¥±RE¥#ff¥, 1, , ,: I:=t=::r5:y;ode.


if (I:::;:i:::3' /-f in i):e:::::::;i:::;:i:::::::E::.
WM CHAR, /* Character received message.

#:EEg#2§EBE: (g:-¥ER5¥£±¥Ey; ;[J / /: ¥:;t=:; ::¥;.


else /* If in overwrite mode, overwrite current character
{ /* with a space.
Winse?£#:g, /* Send sp;:ec:::::C::=d::S::::i:: Self.
WM CHAR, /* Character message.

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 409 .

#:=E8#:SEBE: t¥cT:%t;:. 1, , ,: §::::C:::r::¥;r.


wlnse#:::!i::EBE:(g:i?:::::i:i:,:::;:::;::;:::::ii::;::::e

} /* end overwrite mode */


return TRUE;

) /* end '\b' */
if (CI-IARESG(&msg)->chr == '\t') /* Process a Tab key.
(
Col = 5 -Cursorcol % 5;
whLLew£:::ri:i:i;:§E8R:(¥:i::;:::;:cec}:r;i::i:::::;:;::;::::f

return TRUE;

) /* end '\t' */
if (CHARMSG(&msg)->chr == '\r') /* Process an Enter key.

if (Insert) /* Insert mode is active.


(
InsertLine (CursorLine, Cursorcol) ;
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
wLnse{§¥§::::53±L:3gL:::;::;;::i::€:::;;::§§;::o::roL]bar,

MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WLnEn:i:::::::: ? 1 {:o:::E::e;:i::::I:C:::;t::::::::i±lo?ar) . :;

Rect.xLeft = 0; /* Calculate invalid rectangle. */


Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
WinlnvalidateRect
( hwnd , /: ::¥:::d:::d::C::::1:? be modified. :/
&Rect , /* Dimensions of rectangle to invalidate. */
FALSE) /* Do.n't include descendants w/ WS_CLIPCHILDREN*/

• Figure 8.38..
Tfie C source code file for the example program (continued)
•410 Programmer's Guide to the OS/2 Presentation Manager

Winupdatewindow (hwnd) ; /* Force window update.

} /* end insert mode */


WinsendMsg /* Move cursor down.
(hwnd, /* Client window handle.
WM CHAR, /* Character received message.
MPFROM2SHORT (KC_VIRTUALKEY,1) ,
MPFROM2SHORT (0, VK DOWN)) ;

if (Insert)
LastcursorLine = CursorLine;
winse?!::a, /: ::::nEo::n5:¥ E::a::: to self.
WM CHAR, /* Character received message.

#:EEg#2§g8E: (g:-¥ER=g#f¥' [' ' /: ¥:::u£:yk:gae.


return TRUE;

) /* end '\r' */
if (!I::=:::±::e, /* Insert normal key into file buffer.
CHARMSG ( &msg ) ->chr ,
Cursorcol ,
Insert) )
(
WinAlarm (HWND_DESKTOP, WA ERROR) ;
return TRUE;
)

£:c::±::::t= i:¥::::c::C:a;I::tcoi) * xchar; */


Rect.xRight = min ((GetLineLength (CursorLine) -Firstcol) * xchar, xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
wLn|n:i:§§;;eRect ;; i;¥::;!!::i::::;i::i:i:s:;;:;;::i:g:a:iDREN;;

Winupdatewindow (hwnd) ; /* Force updating of client window.


WinsendMsg /* Send right-key message to self .
( hwnd , /* Client window handle.
" CHAR, /* Character message.
MPFROM2SHORT (KC_VIRTUALKEY,1)
MPFROM2SHORT (0, VK RIGHT)) ;
/* mpl.
/* mp2.
return TRUE;

} /* end Character */

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 411 .

MRESULT EXPENTRY Command (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
USHORT Result; /* WinDlgBox return code. */
USHORT Update = FALSE; /* Flag indicating whether window update needed*/
USHORT Reply; /* Response from message box. */

/*** Branch according to code for the menu item selected. ********************/
switch (COMMANDMSG (&msg)->cmd)
(
case ID NEW: /* 'New' file menu item.
if (Modif led) /* File is modified.
(
/* Warn user and elicit response on saving file.
Reply = WinMessageBox
(HWND DESKTOP,
hwnd '
"File unsaved; Save?",
''PM Text Editor",
0,
MB YESNO I
MB-ICONQUESTION) ;

/* If reply is Yes, send a 'Save' message to client. */


if (Reply == MBID YES)

/* Repeat message until file successfully saved. */


while (Modif led)
WinsendMsg
( hwnd ,
wM comND,
MPFROM2SHORT (ID_SAVE, 0) ,
OL);

} /* end if Modif led */


ReleaseFile () ; /* Free current heap.
NewFile (); /* Initialize a new file.
FileName [0] = '\0'; /* New file is untitled.
ShowFileName () ; /* Display ''Untitled" in title bar.
Modified = 0; /* Reset modified flag.
Initwindow () ; /* Set initial window/cursor values.
return FALSE;
case ID OPEN: /* 'Open' file menu item.

/* Process message using a dialog box.


WinDlgBox
(HWND DESKTOP, /* Handle of parent window: desktop.
hwnd ' /* Handle of owner: client.
Openproc, /* Dialog procedure.

• Figure 8.38..
The C source code file for the example program (continued)
• 412 Programmer's Guide to the os/2Presentation
Manager

NULL' /* Resource module: the .EXE file. */


ID OPENDLG, /* Name ID of dialog window: Open. */
NULL) ; /* Pointer to procedure data: n/a. */
return FALSE;

case ID SAVE: /* 'Save' item of 'File' submenu. */


/* If 'FileName' is non-null, save the file under the
/* current name.
if (FileName [0])
(
if (SaveFile (FileName) == FALSE)

/* Save failed; therefore display a message.


WinMessageBox
(HWND DESKTOP,
HFrame ,
''Error --Cannot Save File",
''PM Text Editor",
0,
MB_OK I
MB_ICONASTERISK) ;

else
/* Save successful; therefore reset 'Modified' flag*/
Modified = 0;

return FALSE;
)
/* IF 'FileName' IS NULL, DROP THROUGH TO ID SAVEAS CASE. */

case ID SAVEAS: /* 'Save As' item of 'File' submenu. */

¢:n::::::S message using a dialog box. */


(HWND DESKTOP, /* Handle of parent window: desktop. */
hwnd ,
Saveasproc , /: E::!:: Sf.::::::. client. :/
NULL' /* Resource module: the .EXE file. */
ID SAVEASDLG, /* Name ID of dialog window: Saveas.*/
NULL) ; /* Pointer to procedure data: n/a. */
return FALSE;
case ID PRINT: /* 'Print' item of 'File' submenu. */
/* Command not implemented.
NotYet ("Print File Command") ;
return FALSE;
case ID EXIT: /* 'Exit' item of 'File' submenu. */
/* Exit program. */
Quit (0);

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 413 .

return FALSE;
case ID ABOUT: /* 'About' item 'File' submenu.

/* Display 'About' box using a dialog box.


WinDlgBox
(HWND DESKTOP, /* Handle of parent window: desktop.
hwnd , /* Handle of owner: client.
Aboutproc , /* Dialog procedure.
NULL, /* Resource module: the .EXE file.
ID ABOUTDLG, /* Name ID of dialog window: About.
NUIL) ; /* Pointer to procedure data: n/a.
return FALSE;
case ID CUT: /* 'Cut' item of 'Edit' submenu.
case ID-COPY: /* 'Copy' item of 'Edit' submenu.
case ID-PASTE: /* 'Paste' item of 'Edit' submenu

/* These commands are not implemented.


NotYet ("Clipboard Commands") ;
return FALSE;

case ID FIND: /* 'Find' item of 'Search' submenu. */

/* Process command through a dialog box.


Result = WinDlgBox
(HWND DESKTOP, /* Handle of parent window: desktop.
hwnd , /* Handle of owner: client.
Findproc, /* Dialog procedure.
NULL, /* Resource module: the .EXE file.
ID FINDDLG, /* Name ID of dialog window: Find.
NUIL) ; /* Pointer to procedure data: n/a.
if (Result) /* Window needs repainting.
(
/* Redisplay window for new position in file.
WinlnvalidateRect /* Invalidate window.
##' ,: ::::::d::ec:::::EW:::::i.
FALSE) ;

Winupdatewindow (hwnd) ; /* Force updating of window.


WinsendMsg /* Set horizontal scroll bar position.
(HHScroll,
SBM SETPOS,
MPFEOM2SHORT (Firstcol,0) ,
0);

WinsendMsg /* Set vertical scroll bar position.


(HVscroll,
SBM SETPOS,
MPFEOM2SHORT (TopLine, 0) ,
0);

• Figure 8.'38:
The C source code file for the example program (continued)
• 414 Programmer's Guide to the os/2Presentation
Manager

return FALSE;
case ID FINDNEXT: /* 'Find Next' item of 'Search' submenu. */

/* Search for string --update cursor position if found.


if (SearchBuf (Findstring, &CursorLine, &Cursorcol) == FALSE)
(
/* String not found.
WinMessageBox
(HWND DESKTOP,
HFrame ,
"String not found",
''PM Text Editor",
0,
MB_OK I
MB_ICONASTERISK) ,.

return FALSE;
)

/* Adjust 'TopLine' for position of found string. */


if (CursorLine < TopLine I I
CursorLine >= TopLine + ywin/ycharTot)
(
TopLine = max (0,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Update = TRUE;
)

/* Adjust 'Firstcol' for position of found string. */


if (Cursorcol < Firstcol I I
Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = max (0,Cursorcol - (xwin/xchar)/2) ;
Firstcol = min (Firstcol,FirstcolMax) ;
Update = TRUE;
)

/* Update window if necessary to display a new file position. */


if (update)
(
WinlnT£:ig:teRect /* Invalidate whole window. */
NULL,
FALSE) ;

Winupdatewindow (hwnd) ; /* Force immediate updating. */


W±nse?S¥Sgro]], /* Adjust horizontal scroll bar. */
SBM SETPOS,
MPFEOM2SHORT (Firstcol, 0) ,
0);

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 415 .

WinsendMsg /* Adjust vertical scroll bar. */


(HVscroll ,
SBM SETPOS,
MPFEOM2SHORT (TopLine, 0) ,
0);
)

/* Reposition the cursor.


Wincreatecursor
( hwnd '
(Cursorcol - Firstcol) * xchar,
ywin - (CursorLine - TopLine + 1) * ycharTot,
0,
0,
CURSOR SETPOS,
NULL) ;

return FALSE;

case ID GOTOLINE: /* 'Go to Line' item of 'Search' submenu. */

/* Process command through a dialog box. **********************/ _1-,

Result = WinDlgBox /* Display dialog box. */


(HWND DESKTOP /* Handle of parent window: desktop. */
*/
hwnd , /* Handle of owner: client. */
Got.oproc, /* Dialog procedure. */
NULL' /* Resource module: the .EXE file */
ID GOTODLG, /* Name ID of dialog window: Goto. */
NUIL) ; /* Pointer to procedure data: n/a
*/
/* If command executed, force updating of entire window.
if (Result)
tinlnvalidateRect /* Invalidate entire window. */
( hwnd '
NULL,
FALSE) ;
Winupdatewindow (hwnd) ; /* Force window update.

WinsendMsg /* Set horizontal scroll bar position.


(HHScroll,
SBM SETPOS,
MPFEOM2SHORT (Firstcol,0) ,
0);

WinsendMsg /* Set vertical scroll bar position.


(HVscroll,
SBM SETPOS,
MPFEOM2SHORT (TopLine, 0) ,
0);

return FALSE;

• Figure 8.,38..
The C source code file for the example program (continued)
•416 Programmer's Guide to the OS/2 Presentation Manager

case ID INSERT: /* 'Overwrite Mode'/'Insert Mode' item


/* 'Options' submenu.
Insert A-1; /* Toggle 'Insert' global flag.
return FALSE;

default :
return FALSE;

} /* end switch */
} /* end Command */

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPAFun mpl, MPARAM mp2)
(

::ST#:==::§a::trics; /: :::::::i:i:: ::::ef:::d::iensions.


LONG Numberstructs = 1; /* Number of structures from GpiQueryFonts.
GpiLoadFonts /* Load Courier font.
(HAncBlk, /* Anchor block handle.
"\\OS2\\DLL\\COURIER.FON"); /* Full path name of font file.

Hpresspace = WinGetps (hwnd) ;

GpiQueryFonts /* Obtain information on Courier font.

i:::i:::i::, ;; ;:::::::: ;::::::a::::s:pace.


&Numberstructs, /* Number of FONTMETRICS structures returned
(long)sizeof (FONTMETRICS) ,/* Length of structure for EACH font.
&Metrics) ; /* Address of FONTMETRICS structure(s).

xchar = (SHORT) Metrics. IAvecharwidth;


ycharTot = (SHORT)Metrics.IMaxBaselineExt;
ycharDesc = (SHORT)Metrics.IMaxDescender;
FontAttributes.usRecordLength = sizeof (FontAttributes) ;
FontAttributes. fsselection = Metrics. fsselection;
FontAttributes.IMatch = Metrics.IMatch;
strcpy (FontAttributes. szFacename,Metrics. szFacename) ;
FontAttributes. idRegistry = Metrics. idRegistry;
FontAttributes.uscodepage = Metrics.uscodepage;
FontAttributes. IMaxBaselineExt = Metrics. IMaxBaselineExt;
FontAttributes. IAvecharwidth = Metrics. IAvecharwidth;
FontAttributes. fsType = FATTR TYPE F'IXED;
FontAttributes. fsFontuse = 0;
WinReleaseps (Hpresspace) ;
HHScroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW_PARENT,FALSE) , /* Handle to parent */
FID_HORZSCROLL) ; /* |dentifier £:rwt:::¥cffr::::ii bar. :/

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 417 .

HVscroll = WinwindowFromlD
(WinQuerywindow (hwnd, QW PARENT,FALSE) , /* Handle to parent */
/* window (frame). */
FID VERTSCROLL) ; /* Identifier for vertical scroll bar. */
return FALSE;

} /* end Create */

MRESULT EXPENTRY Help (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
NotYet ("Help Window") ;
return FALSE;

) /* end Help */

MRESULT EXPENTRY HScroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SHORT Delta; /* Amount to scroll.
switch (SHORT2FROMMP (mp2) ) /* Branch according to code for the
{ /* scrolling event.
case SB LINELEFT:
Delta --1;
break;
case SB LINERIGHT:
Delta -1;
break;
case SB PAGELEFT:
Delta --6;
break;
case SB PAGERIGHT:
Delta -6;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -Firstcol;
break;
default:
Delta -0;
break;
)
Delta = max (-Firstcol, min (Delta,FirstcolMax -Firstcol)) ;
if (Delta) /* Generate scrolling, if necessary.
(
Firstcol += Delta;
Cursorcol += Delta;
Winshowcursor /* Hide cursor.
( hwnd , /* Client window handle.
FALSE) ; /* Hide it!
Winscrollwindow /* Scroll window horizontally.

• Figure 8.3.8:
The C source code file for the example program (continued)
• 418 Programmer's Guide to the os/2PresentationManager

(hwnd, /* Handle of client window.


-Delta * xchar, /* Horizontal scroll amount.
0, /* Vertical scroll amount.
0' /* Must be 0.
0, /* Must be 0.
0, /* Must be 0.
0' /* Must be 0.
SW INVALIDATERGN) ; /* Invalidate "exposed" region.

Winupdatewindow /* Force updating of client window. */


(hwnd) ; /* Handle of client window. */
WinsendMsg /* Adjust horizontal slider position
(HHScroll, /* Handle to horizontal scroll bar.
SBM SETPOS, /* Set position of slider.
MPFEOM2SHORT (Firstcol,0) , /* Current position.
0) ; /* Second parameter: n/a.
Wincreatecursor /* Set position of cursor.
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position.
0, /* x size of cursor: n/a.
0, /* y size of cursor: n/a.
CURSOR SETPOS, /* Option to set position only.
NULL) ; /* Clipping rectangle: n/a
Winshowcursor /* Show cursor.
( hwnd , /* Client window handle.
TRUE) ; /* Show it!
} /* end if (Delta) */
return FALSE;

} /* end HScroll */

MRESULT EXPENTRY InitMenu (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

/*** Branch on the code for the specific submenu that is being displayed. ****/
switch (SHORTIFROMMP (mpl) )
(
case ID EDIT: /* 'Edit' submenu.
WinsendMsg /* Set attribute of 'Cut' menu item.
( HMenu , /* Handle of menu window.
MM SETITEMATTR, /* Set attribute of menu item.
MPFROM2SHORT
( I D_CUT ' /* 'Cut' menu item.
TRUE) ' /* Include submenus.
MPFROM2SHORT
(MIA DISABLED, /* Disabled attribute.

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 419 .

/* Disable only if block not marked. */


BlockMarked ? 0 : MIA DISABLED)) ;

WinsendMsg /* Set attribute of 'Copy' menu item.*/


( HMenu , /* Handle of menu window. */
MM SETITEMATTR, /* Set attribute of menu item. */
MPFROM2 SHORT
( I D_COPY , /* 'Copy' menu item. */
TRUE) , /* Include submenus. */
MPFROM2SHORT
(MIA DISABLED, /* Disabled attribute. */
/* Disable only if block not marked. */
BlockMarked ? 0 : MIA DISABLED)) ;

WinsendMsg /* Set attribute of 'Paste' menu item*/


( HMenu , /* Handle of menu window. */
MM SETITEMATTR, /* Set attribute of menu item. */
MPFROM2SHORT
( I D_PASTE , /* 'Paste' menu item. */
TRUE) , /* Include submenus. */
MPFROM2 S HORT
(MIA DISABLED, /* Disabled attribute. */
/* Disable if no data in clipboard. */
ClipData ? 0 : MIA DISABLED) ) ;

return FALSE;
case ID SEARCH: /* 'Search' submenu. */
WinsendMsg /* Set attribute of 'Find Next' item.*/
( HMenu , /* Handle of menu window. */
MM SETITEMATTR, /* Set attribute of menu item. */
MPFROM2SHORT
( I D_FINDNEXT , /* 'Find Next' menu item. */
TRUE) , /* Include submenus. */
MPFROM2 SHORT
(MIA DISABLED, Disabled attribute */
Disable if no search string given.*/
Findstring [0] : MIA DISABLED) ) ;

return FALSE;

case ID OPTIONS: /* Options submenu.


/* Set menu item text according to current insert status.
WinsendMsg
(HMenu, /* Menu handle.
MM SETITEMTEXT, /* Set item text.
MPFROM2SHORT (ID INSERT,0), /* ID of item.
Insert ? (MPARAMT(PCH)"Overwrite Mode\tlns" /* Text.
: (MPARAM) (PCH)"Insert Mode\tlns") ;

return FALSE;

default:

• Figure 8.38..
The C source code file for the example program (continued)
• 420 Programmer's Guide to the os/2PresentationManager

return FALSE;

) /* end switch */
} /* end InitMenu */

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
register int Line; /* Loop counter.
HPS Hpresspace; /* Presentation space handle.
RECTL Rect; /* Holds coordinates of rectangle.
SHORT StartLine; /* First file line to paint.
SHORT StopLine; /* Last line to paint.
POINTL Start; /* Starting position to print string
SHORT LineLength; /* Length of each line displayed.
Hpresspace = WinBeginpaint
( hwnd ' /* Window handle. */
0, /* Handle of PS to have clipping region set. */
&Rect) ; /* Address of struct. to set to invalid region.*/
GpicreateLogFont /* Create a logical font for presentation space*/
( Hpresspace , /* Presentation space handle. */
( PSTR8 ) NULL , /* Logical font name: none. */
ID COURIER, /* Local font ID: define a constant. */
&F6ntAttributes) /* Struct. specifying font from GpiQueryFonts. */
Gpisetcharset /* Make logical font the current character set.*/
( Hpresspace , /* Presentation space handle. */
ID COURIER) ; /* Local font ID. */
WinF i l lRect
( Hpresspace , /* Presentation space handle. */
&Rect , /* Structure containing window coordinates. */
CLR WHITE) ; /* Color to use (white) . */

Gpisetcolor
(Hpresspace, /* Presentation space handle. */
CLR BI.ACK); /* Color to use: black. */
StartLine = TopLine + (ywin - (SHORT)Rect.yTop) / ycharTot;
StopLine = min (LastLine, TopLine + (ywin - (SHORT)Rect.yBottom)
/ ycharTot) ;
Start.y = ywin -ycharTot * (StartLine -TopLine + 1) + ycharDesc;
Start.x = xchar * (-Firstcol) ;
for (Line = StartLine; Line <= StopLine; ++Line, Start.y -= ycharTot)
(
if ((LineLength = GetLineLength (Line)) == 0)
continue;
GpicharstringAt Prints string at given position
(Hpresspace , Presentation space handle.
&Start, Structure containing starting position. *
( LONG ) LineLength , Number of characters to print. *
GetLineAddr (Line) ) Address of line. *

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 421 .

WinEndpaint (Hpresspace) ;

return FALSE;

) //* end Paint */

MRESULT EXPENTRY SetFocus (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
if (LONGFROMMP (mp2)) /* Client window RECEIVING focus.
(
Wincreatecursor /* Create a new cursor.
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position
0' /* x size of cursor: nominal border
ycharTot , /* y size of cursor.
CURSOR_SOLID I /* Solid cursor.
CURSOR FIASH, /* Blinking cursor.
NULL) ; /* Clipping rectangle: entire window.
Winshowcursor /* Make cursor visible.
( hwnd , /* Client window handle.
TRUE) ; /* Show it!
)

else /* Client window LOSING focus.


WinDestroycursor (hwnd) ;
ret.urn FALSE;

} /* end SetFocus */

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
int Update = 0;

ywin = SHORT2FROMMP (mp2) ;


xwin = SHORTIFROMMP (mp2) ;

/* Scroll window if necessary so that cursor position is visible.


if (CursorLine >= TopLine + ywin / ycharTot)
(
TopLine = CursorLine -ywin / ycharTot + 1;
Update -1;
)
if (Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = Cursorcol -xwin / xchar + 1;
Update -1;
)
if (Update)

• Figure 8.38..
The C source code file for the exanple program (continued)
• 422 Programmer's Guide to the os/2 PresentationManager

WinlnvalidateRect /* Invalidate entire window.


( hwnd ' /* Client window handle.
0, /* Rectangle: 0 means whole window.
FALSE) ; /* Do not automatically include children
/* Re-create the cursor if client window has focus
if (hwnd == WinQueryFocus /* Does client have focus?
(HWND DESKTOP, /* Must give desktop handle.
FALSET) /* Do not lock window.
(
WinDestroycursor (hwnd) ; /* Destroy existing cursor.
Wincreatecursor /* Create a new cursor.
( hwnd , /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine -TopLine + 1) * ycharTot, /* y position
0, /* x size of cursor: nominal border.
ycharTot, /* y size of cursor.
CURSOR SOLID /* Solid cursor.
CURSOR-FLASH /* Flashing cursor.
NULL) ; /* Clipping rectangle: entire window
Winshowcursor /* Make cursor visible.
( hwnd , /* Client window handle.
TRUE) ; /* Show it!
)

TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;


TopLine = min (TopLine,TopLineMax) ;

WinsendMsg /* Adjust range/position of slider.


(HVscroll, /* Recipient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set position & range.
MPFEOM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable scroll bar if scrolling is possible. *


(HVscroll, /* Recipient handle (vertical scroll bar).*
TopLineMax ? TRUE : FALSE); /* Enable only if max. != 0. *

FirstcolMax = LINEBUFSIZ - 2 - xwin / xchar;


Firstcol = min (Firstcol, FirstcolMax) ;
WinsendMsg /* Adjust range/position of slider. */
(HHScroll, /* Recipient handle: horizontal scroll bar*/
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (Firstcol, 0) , /* Position.
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range.

return FALSE;

} /* end Size */

MRESULT EXPENTRY VirtKey (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 425 .

if (Newcursorcol > Firstcol + xwin / xchar - 1)


(
NewFirstcol = Newcursorcol -xwin / xchar + 1;
Update -1,
)
else if (Newcursorcol < Firstcol)
(
NewFirstcol = Newcursorcol;
Update -1,
)
if (Update)
WinsendMsg /* Scroll window to new position. */
( hwnd ,
WM HSCROLL,
OL,
MPFROM2SHORT (NewFirstcol ,
SB SLIDERPOSITION) ) ;

Cursorcol = Newcursorcol;
break;
case VK DELETE: /* Delete key. */

/*** Set global 'Modified' flag. ***********************************/


Modified = 1;
*/
/* Adjust file buffer if necessary.
if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)

if (Deletechar (CursorLine,Cursorcol) )
(
/* Deletion successful -- invalidate update region. */
Rect.xLeft = (Cursorcol -Firstcol) * xchar;
Rect.xRight = min
((GetLineLength (CursorLine) + 1 -Firstcol) * xchar,
xwin) ;
Rect.yBottom = ywin - (CursorLine -TopLine + 1) * ycharTot;
Rect.yTop = Rect.yBottom + ycharTot;
WinlnvalidateRect /* Invalidate region to be updated. */
( hwnd '
&Rect,
FALSE) ;

Winupdatewindow (hwnd) ; /* Force client window update. */


)
return TRUE;

case VK F9: /* F9 key: delete line. */

• Figure 8.38..
The C source code file for the example program (continued)
• 426 Programmer's Guide to the os/2 Presentation Manager

/*** Set global 'Modified' flag. ***********************************/


Modified = 1;

/* If modifying new line, must place line in temporary buffer.*/


if (LastcursorLine != CursorLine)
(
ReleaseTempBuf (LastcursorLine) ;
GetTempBuf (CursorLine) ;
LastcursorLine = CursorLine;
)

/* Delete line containing the cursor.


DeleteLine (CursorLine) ;

/* Adjust 'TopLineMax' / scroll bar range for new file length.*/


TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
WinsendMsg
(HVscroll, /* Recipient handle.
£BfE3Eg!Sg3EL?3:6Line, o), /: S::i::::tion & range.
MPFROM2SHORT (0, TopLineMax)) ; /* Range.
WinEnablewindow
(HVscroll, /* Recipient handle. */
TopLineMax ? 1 : 0); /* Enable only if max.!= 0*/

/* Invalidate 'CursorLine' and all lines below. */


Rect.xLeft = 0;
Rect.xRight = xwin;
Rect.yTop = ywin - (CursorLine -TopLine) * ycharTot;
Rect.yBottom = 0;
WinlnvalidateRect /* Invalidate section to be modified.
(hwnd, /* Handle of client window.
&Rect, /* Rectangle to be added to invalid region
FALSE) ; /* No descendants w/ WS CLIPCHILDREN.

Winupdatewindow (hwnd) ; /* Force updating of client window. */


return TRUE;
default: /* All other virtual codes. */
return FALSE;

} /* end virtual key switch */


Wincreatecursor /* Set position of cursor.
(hwnd, /* Client window handle.
(Cursorcol - Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position.
0, /* x size of cursor: n/a.
0, /* y size of cursor: n/a.
CURSOR SETPOS /* Option to set position only.
NULL) ; /* Clipping rectangle: n/a
return TRUE;

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 427 .

} /'* end VirtKey */

MRESULT EXPENTRY Vscroll (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
SI-[ORT Delta; /* Amount to scroll.
switch (SHORT2FROMMP (mp2)) /* Switch on code for scrolling event. */
(
case SB LINEUP:
Delta --1;
break;
case SB LINEDOWN:
Delta -1;
break;
case SB PAGEUP:
Delta = -ywin / ycharTot;
break;
case SB PAGEDOWN:
Delta = ywin / ycharTot;
break;
case SB SLIDERPOSITION:
Delta = SHORTIFROMMP (mp2) -TopLine;
break;
default:
Delta -0;
break;
)
Delta = max (-TopLine, min (Delta,TopLineMax -TopLine)) ;

if (Delta)
(
TopLine += Delta;
CursorLine += Delta;
Winshowcursor /* Hide the cursor.
( hwnd ' /* Client window handle.
FALSE) ; /* Hide it!
Winscrollwindow /* Scroll window vertically.
( hwnd ' /* Handle of client window.
0, /* Horizontal scroll amount.
ycharTot * Delta, /* Vertical scroll amount.
0, /* Must be 0.
0, /* Must be 0.
0' /* Must be 0.
0' /* Must be 0.
SW INVALIDATERGN) /* Invalidate "exposed" region.
Winupdatewindow /* Force window update.
(hwnd) ; /* Handle of client window.
WinsendMsg /* Adjust vertical scroll bar.
(HVscroll, /* Handle to vertical scroll bar.
SBM SETPOS, /* Set position of slider.

• Figure 8.'38:
The C source code file for the exanple program (continued)
• 428 Programmer's Guide to the os/2 Presentation Manager

MPFROM2SHORT (TopLine,0) ,/* Current position.


0) ; /* Second parameter n/a.
Wincreatecursor /* Set position of cursor.
(hwnd, /* Client window handle.
(Cursorcol -Firstcol) * xchar, /* x position of cursor.
ywin - (CursorLine - TopLine + 1) * ycharTot, /* y position.
0, /* x size of cursor: n/a.
0' /* y size of cursor: n/a.
CURSOR SETPOS, /* Option to set position only.
NULL) ; /* Clipping rectangle: n/a
Winshowcursor /* Restore cursor visibility.
( hwnd , /* Client window handle.
TRUE) ; /* Show it!
} /* end if (Delta) */
return FALSE;

} /* end Vscroll */

/*** Dialog window procedures. ***********************************************/

MRESULT EXPENTRY Aboutproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
/*
Process dialog messages for the 'About' dialog box.
*/
(
switch (msg)
(
/*** Process WM_COMMAND messages sent by 'About' dialog box controls. ***/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Ok' button or pressed Enter key. ********/
case DID OK:

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:
Win5ismissDlg (hwnd,TRUE) ;
return FALSE;
default :
return FALSE;
)
default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 429 .

} /* end Aboutproc */

MRESULT EXPENTRY Findproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
char Buffer [2]; /* Holds first character of entered file name. */
USHORT Update = FALSE; /* Flag indicates whether window update needed.*/
switch (msg)
(
/* Process WM_COMMAND messages sent by dialog controls. *****************/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Find' button or pressed Enter key. ******/
case DID 0K:

/* Obtain text from 'Find:' edit box. */


WinQuerywindowText
(WinwindowFromlD (hwnd, ID_FINDEDIT) ,
sizeof (Findstring) ,
Findstring) ;

/* If search string empty, return immediately. */


if (Findstring [0] == '\0')
return FALSE;

/* Search for string. */


if (SearchBuf (Findstring, &CursorLine, &Cursorcol) ==
FALSE)

;* Display message if string not found. */


WinMessageBox
(HWND DESKTOP,
hwnd, /* Note: parent is dialog window*/
"String not found",
''PM Text Editor",
0,
MB OK I
MB-ICONASTERISK) ;

/* Remove dialog box.


WinDismissDlg (hwnd, FALSE) ;
return FALSE;
)

/* Adjust 'TopLine' for new cursor position.


if (CursorLine < TopLine I I
CursorLine >= TopLine + ywin/ycharTot)
(
TopLine = max (0,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Update = TRUE;

• Figure 8.,38..
The C so'urce code file for the example program (continued)
•430 Programmer's Guide to the OS/2 Presentation Manager

/* Adjust 'Firstcol' for new cursor position. */


if (Cursorcol < Firstcol I I
Cursorcol >= Firstcol + xwin / xchar)
(
Firstcol = max (O,Cursorcol - (xwin/xchar)/2) ;
Firstcol = min (Firstcol,FirstcolMax) ;
Update = TRUE;
)
/* Remove dialog box, returning flag indicating
/* whether window must be updated.
WinDismissDlg (hwnd, Update) ;
return FALSE;
*** :::: s±3c5£Sc:E:,cancel, button or pressed Escape key. *,

/* Remove dialog box.


WinDismissDlg (hwnd,FALSE) ;
return FALSE;

default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit field. ********************/

case WM CONTROL:

switch (SHORTIFROMMP (mpl) )


(
/*** Message sent by edit box. ********************************/
case ID FINDEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:
/* Get new text.
WinQuerywindowText
((HWND) mp2,
2,
Buf fer) ;
/* Enable 'Find' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 431 .

/*** Process WM_INITDLG message sent when dialog box first displayed. ***/
case WM INITDljG:

/* Display initial value of 'Findstring' in edit box. */


WinsetwindowText
(WinwindowFromlD (hwnd, ID_FINDEDIT) ,
Findstring) ;
default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

} /* end Findproc */

MRESULT EXPENTRY Gotoproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
char NumberBuf [33] ;
char Buffer [2];
S]ioRT LineNumber;

switch (msg)
(
/*** Process WM_COMMAND messages sent by dialog controls. ***************/
case WM COI\"AND:

switch (COMMANDMSG(&msg) ->cmd)


(
/*** User clicked on 'Go to` button or pressed Enter key. *****/
case DID OK:

/* Obtain text from 'Go to Line' edit box. */


WinQuerywindowText
(WinwindowFromlD (hwnd, ID_GOTOEDIT) ,
sizeof (NumberBuf ) ,
NumberBuf ) ;

/* Convert to numeric value and continue if > 0. */


LineNumber = atoi (NumberBuf ) ;
if (LineNumber <= 0)
return FALSE;

/* Set global cursor and window position variables. */


--LineNumber;
CursorLine = min (LastLine,LineNumber) ;
TopLine = max (0,CursorLine - (ywin/ycharTot)/2) ;
TopLine = min (TopLine,TopLineMax) ;
Cursorcol = Firstcol = 0;

/* Remove dialog box.

• Figure8.38:
The C source code file for the example program (continued)
®432 Programmer's Guide to the OS/2 Presentation Manager

WinDismissDlg (hwnd, TRUE) ;


return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. */


case DID CANCEL:

/* Remove dialog box.


WinDismissDlg (hwnd,FALSE) ;
return FALSE;

default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit field. ********************/

case WM CONTROL:

switch (SHORTIFROMMP (mpl) )


(
case ID GOTOEDIT:
switch (SHORT2FROMMP (mpl) )
(
/*** User altered the text. *************************/
case EN CHANGE:
/* Get new text.
WinQuerywindowText
((HWND) mp2,
2'
Buf fer) ;
/* Enable 'Go to' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;
)

/*** Process WM_INITDLG message sent when dialog box first displayed. ***/
case WM INITDLG:

¢:n==::i::±Xd:;Sable 'Go to' button (until text entered). */


(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;
return FALSE;
default :
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 433 .

} /* end Gotoproc */
VOID InitDlg (HWND hwnd) ; /* Initializes the 'Open' dialog box. */

MRESULT EXPENTRY Openproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
/*
Processes messages sent to 'Open' dialog box.
*/

S]IO:RT selectlndex; /* Index of selected item in 'Open' list box. */


char Buffer [16] ; /* Temporary storage for text. */
static char Filepath [PATHLENGTH] ; /* Holds file path string. */
USHORT Reply; /* Response from message box. */

switch (msg)
(
/*** Process WM COMMAND messages sent by dialog controls. ***************/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Open' button or pressed Enter key. ******/
case DID OK:
/* 5btain text from edit box. */
WinQuerywindowText
(WinwindowFromlD (hwnd, ID OPENEDIT) ,
sizeof (Filepath) ,
Filepath) ;

/* If a file name is entered, try to read the file. */


if (Filepath [0])
(
if (Modified) /* File is modified.
(
/* Warn user and elicit response on
/* saving file.
Reply = WinMessageBox
(HWND DESKTOP,
hwnd ,
"File unsaved; Save?",
"PM Text Editor",
0,
MB YESNO I
MB-ICONQUESTION) ;

/* If reply is Yes, send a 'Save' menu */


/* message to client. */
if (Reply == MBID YES)

/* Repeat message until f ile */


/* successfully saved. */
while (Modif ied)

• Figure 8.38..
The C source code file for the example program (continued)
• 434 Programmer's Guide to the os/2 Presentation Manager

WinsendMsg
(Hclient'
" ComND,
MPFROM2SHORT (ID SAVE, 0) ,
OL);

} /* end if Modified */
ReleaseFile () ; /* Free current heap. */

/* Read the new file.


if (ReadFile (F'ilepath))
(
/* Warn user if read error occurred.
WinMessageBox
(HWND DESKTOP,
hwnd '
''Error --Cannot Read File",
"PM Text Editor",
0'
MB_OK I
MB ICONASTERISK) ;

FileName [0] = '\0'; /* Null file name. */


NewFile () ; /* New file instead.*/
)
/* File was successfully read.
else
/* Store fully qualified path name.
Qualify (Filepath, FileName) ;
ShowFileName () ; /* Display name in title bar.
¥::::i:go= :,; ; ,: §::e:i::::;:::s::a3;Lues.

¢:n3:::¥:s::; dialog box. */


(hwnd, /* Handle of dialog window. */
retur:R¥EisE; /* code returned by winDigBox. */
)

return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:

/* Remove the dialog box.


WinDismissDlg
( hwnd , /* Handle of dialog window. */
TRUE) ; /* Code returned by WinDlgBox. */
return FALSE;

default:
return FALSE;

• Figure 8.38..
The C source code fie for the exanple program (continued)
DesigningDialogBoxes 435 .

/*** Process WM CONTROL messages sent by edit box or list box. **********/
case WM CONTROL:

switch (SHORTIFROMMP (mpl) )


(

/*** Message sent by edit box. ********************************/


case ID OPENEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:
/*-Get the new text. */
WinQuerywindowI'ext
((HWND) mp2,
2'
Buf fer) ;
/* Enable 'Open' button if text present. */
WinEnablewindow
(WinwindowFromlD (hwnd, DID OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)

/*** Message sent by list box. ********************************/


case ID OPENLIST:
/*-Get index of selected item. */
Selectlndex = (SHORT) WinsendDlgltemMsg
( hwnd ,
ID OPENLIST,
IjM-QUERYSELECTION,
OLT
OL);
/* Get text belonging to selected item.
WinsendDlgltemMsg
( hwnd ,
ID OPENLIST,
IjM-QUERYITEMTEXT,
MPFROM2SHORT (Selectlndex, sizeof (Buffer) ) ,
MPFROMP (Buffer) ) ;

/* Branch on code for specific evenc.


switch (SHORT2FROMMP (mpl) )
(
/* User pressed Enter key or double clicked. */
case LN ENTER:
/*-Item is for a drive letter.
if (Buffer [0] == '[' &&
Buffer [1] == '-')
(

• Figure 8.38..
The C source code file for the example program (continued)
• 436 Programmer's Guide to the os/2 Presentation Manager

/* Change to specified drive. */


DosselectDisk (Buffer [2] -64);
/* Update dialog box data. */
InitDlg (hwnd) ;
)
/* Item is for a directory. */
else if (Buffer [0] == '[')
(
/* Null terminate after directory. */
Buffer [strlen (Buffer) -1] = '\0';
/* Change to new directory. */
DoschDir
(Buffer + 1,
OL);
/* Update dialog box data.
InitDlg (hwnd) ;
)
/* Item is a file name.
else if (Buffer [0])
(
/* Save the file by sending message. */
WinsendMsg
(hwnd, /* Dialog window hand.*/
#F:gE3iT (Df; g:::;?e ID. */
OL);

/* Remove the dialog box. */


WinDismissDlg (hwnd, TRUE) ;
return FALSE;
)
return FALSE;

/* New item is selected (highlighted) .


case LN SELECT:
/*-Null string for drive or directory.
if (Buffer [0] == '[')
Buffer [0] = '\0';
/* Place selected text in edit box.
WinsetwindowText
(WinwindowFromlD (hwnd,ID OPENEDIT) ,
Buf fer) ;
return FALSE;
default:
return FALSE;
)

default:
return FALSE;
)

/*** Process WM_INITDLG message sent when dialog box first displayed. ***/
case WM INITDLG:

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 437 .

/* Expand text limit in edit box to full file path length. */


WinsendDlgltemMsg
( hwnd ,
ID 0PENEDIT,
EM-SETTEXTLIMIT ,
MPFROM2SHORT (PATHLENGTH, 0) ,
0);

/* Initially disable the 'Open' button until text is entered. */


WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;

/* Display initial directory and list box data.


InitDlg (hwnd) ;
return FALSE;

default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;

} /* end switch */
} /* end Openproc */

VOID InitDlg (HWND hwnd)


/* Called by 'Openproc' to display current data in 'Current Directory' field
and list box of 'Open' dialog box.
*/
(
register int Drive; Disk drive letter
USHORT DriveNumber; Disk drive number
ULONG LogicalDrives; Mapping of installed drives.
char Buffer [PATHLENGTH] ; Holds file paths.
HDIR Hsearch = 1; OS/2 file search handle.
FILEFINDBUF FindBuf ; Structure for f ile searches
USHORT Filecount = 1; Count files to find/found.
char *Ptrch; Temporary character pointer

/*** Obtain current default drive path. **************************************/


Getpath (Buffer, sizeof (Buffer)) ;

/*** Display current drive and directory path in 'Current Directory' field. **/
W i ns etw i ndowText
(WinwindowFromlD (hwnd, ID OPENCD)' /: 5:r::t::;Tr:::id
Buf fer) ; /* Buffer containing text to display.
/*** Obtain current default disk and mapping of installed drives. ************/
DosQCurDisk
( & Dr iveNumber , /* Receives number of current drive. */

• Figure 8®38:
The C source code file for the example program (continued)
• 438 Programmer's Guide to the os/2Presentation
Manager

&LogicalDrives) ; /* Receives mapping of installed drives. */

/*** Clear all existing entries from the list box. *„"**"*****************/
WinsendDlglte"sg
L7ir`CanAnl~T+,^_`f-~ 7. ~
/* Send message to dialog item. */
( hwnd , /* Handle of dialog window. */
ID OPENLIST, /* ID of list box. */
"-DELETEALL, /* Delete all entries. */
0, /* mpl: not used. */
0);
/* mp2: not used. */
/*** Insert drive letters into list box. ********************"*„************/
for (Drive = 'A'; Drive <= 'Z'; ++Drive)
(
if (LogicalDrives & 1)
(
sprintf (Buffer,"[-%c-]",Drive) ;
WLnsei§:§§;;;T¥;:M, ;; i;:i:::§§::i:i:gd:::3gw:ten.

MPFROM2SHORT (LIT_SORTASCENDING, 0) , /* Ascending sort

MPFROMP (Buffer));
/* Order.
/* Address of item text.
)
LogicalDrives >>= 1;
)

/*** Insert directories and files into list box. *****************************/

5:s=±::Ff:::t directory or file. *,

i:!§:::;;:?dBuf) , ;; ¥::;::::;:::=:¥:::i:i;::::i::::::on;;
¢:i::°:i::e::::tTatch±ng file. *,

: |fi:::::.::t:F:i:e:t:=¥6Lgu:&N°T '.'' insert it in list box. */


!(FindBuf.achName [0] == '.I && FindBuf.achName [1] == '\0'))
(
sprintf (Buffer,"[%s]",FindBuf.achName) ;
--,_-
WinsendDlgltemMsg /* See above.
( hwnd ,
ID OPENLIST,
I-M-INSERTITEM,
MPFROM2SHORT (IjlT_.SORTASCENDING, 0) ,
MPFROMP (Buffer) ) ;
)
/* If match is a normal file, insert only if it has the .TXT or

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 439 .

/* .C extension.
else if (strcmp ((Ptrch = Extension (FindBuf.achName)),"TXT") == 0
I I strcmp (Ptrch,"C") == 0)
WinsendDlgltemMsg /* See above.
( hwnd ,
ID OPENLIST,
I"-INSERTITEM,
MPFROM2SHORT (LIT SORTASCENDING, 0) ,
MPFROMP (FindBuf .=chName) ) ;

/* Find NEXT matching file.


DosFindNext
(Hsearch, /* Search handle returned by DosFindFirst.*
&FindBuf, /* Receives information on matching file. *
sizeof (FindBuf ) /* Length of receiving buffer. *
&Filecount) ; /* Retdrns number of matching files left. *
)

) /* end InitD19 */

MRESul\T EXPENTRY Saveasproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

Processes dialog messages for the 'Save As' dialog box.


*/
cha£ Filepath [PATHLENGTH]; /* Holds file path. */
char CurDir [PATHLENGTH + 22] ; /* Holds contents of 'Current Directory' .*/
char Buffer [2]; /* Holds first character of entered file name. */
switch (msg)
(
/*** Process WM COMMAND messages sent by dialog controls. ********************/
case WM COMMAND:

switch (COMMANDMSG (&msg) ->cmd)


(
/*** User clicked on 'Save' button or pressed Enter key. ******/
case DID OK:

/* Obtain text from 'Save As' edit box. */


WinQuerywindowText
(WinwindowFromlD (hwnd, ID_SAVEASEDIT) ,
sizeof (Filepath) ,
Filepath) ;
/* If path string not empty, save file/remove dialog*/
if (Filepath [0])
(
/* Save under the new name.
if (SaveFile (Filepath) == FALSE)

/* Display error message if save failed. */


WinMessageBox

• Figure 8.38..
The C source code file for the example program (continued)
•440 Programmer's Guide to the OS/2 Presentation Manager

(HWND DESKTOP,
hwnd '
''Error --Cannot Save File",
''PM Text Editor",
0,
MB_OK I
MB_ICONASTERISK) ;
else
(
/* Store fully qualified path name.
Qualify (Filepath, FileName) ;

/* Display the new name in title bar.


ShowFileName () ;

/* Reset 'Modified' flag.


Modified = 0;
)

/* Remove dialog box.


WinDismissDlg (hwnd, TRUE)
return FALSE;
)

return FALSE;

/*** User clicked on 'Cancel' button or pressed Escape key. ***/


case DID CANCEL:

/* Remove the dialog box.


WinDismissDlg (hwnd,TRUE) ;
return FALSE;
default:
return FALSE;
)

/*** Process WM_CONTROL messages sent by edit box. **********************/

case WM CONTROL:
switch (SHORTIFROMMP (mpl) )
(
/*** Message sent by edit box. ********************************/
case ID SAVEASEDIT:

switch (SHORT2FROMMP (mpl) )


(
/*** User altered the text. *************************/
case EN CHANGE:

#:8:: r;:Tn::::;xt */
((HWND) mp2,
2'
Buf fer) ;
/* Enable 'Save' button if text present. */

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 441 .

WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
Buffer [0]) ;
return FALSE;
default:
return FALSE;
)
default:
return FALSE;
)

/.it** Process WM_INITDLG message sent when dialog box first displayed. ***/
Case y¥-=¥::::Giext limit in edit box to full file path length. */
WinsendDlgltemMsg
( hwnd ,
ID SAVEASEDIT,
EM-SETTEXTLIMIT ,
MPFROM2SHORT (PATHLENGTH, 0) ,
0);

/* Initially disable the 'Save' button until text is entered. */


WinEnablewindow
(WinwindowFromlD (hwnd, DID_OK) ,
FALSE) ;

/* Obtain current directory path.


Getpath (Filepath, sizeof (Filepath)) ;

/* Format string for 'Current Directory' field.


sprintf (CurDir,"Current Directory: %s",Filepath)

/* Display string in 'Current Directory' field.


WinsetwindowText
(WinwindowFromlD (hwnd, ID_SAVEASCD) , /* ID of */
/* 'Current Directory' field. */
CurDir) ; /* String to display. */
return FALSE;

default:
/* Execute default processing for all other messages.
return WinDefDlgproc (hwnd, msg, mpl, mp2) ;
)

} /* end Saveasproc */

/*** Function used by the window procedures. ********************************/


void NotYet (char *Message)
(
char Buffer [60];

• Figure 8.38..
The C source code file for the example program (continued)
• 442 Programmer's Guide to the os/2Presentation
Manager

/* Format message.
sprintf (Buffer,"Not Yet Implemented: %s",Message) ;

WinMessageBox /* Display a message box.


(HWND DESKTOP, /* Handle of parent --try frame.
HFrame , /* Handle of owner.
Buffer, /* Message text.
"PM Text Editor",
/* Caption.
0' /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB_ICONASTERISK) ; /* Display an exclamation.
} /* end NotYet */

/*** Buffer-management module ************************************************/

#define MAXLINES 4096 /* Maximum number of lines in file buffer.*/


static struct /* Stores information on each line.
(
PCH LineAddress; /* Far address of block containing line.
unsigned char LineLength; /* Length of line (includes \n and \0) .
)
LineTable [MAXLINES] ;

::;::: :::::::i:i:::i;:;:::?uFSIZ` i #::;:::::::;::::;i;:::::


void?uflnit (void) /* Initializes the buffer management module.
PCH Farptr;

Farptr = (char far *)LineBuffer;


Lineselector = SELECTOROF (Farptr) ;
Lineoffset = OFFSETOF (Farptr) ;

} /* end Buflnit */

int Deletechar /* Deletes a character from 'LineBuffer'.


!:g::Tc:i::i, ,: ::::e:o::a:::::c:::r::t:: E!i_EE:i:I:t;d.
/*
This function deletes the indicated character from 'LineBuffer'. It
returns TRUE if the buffer was modified, and FALSE if no action took
place (i.e., the specified character was beyond the visible end of the
line) .
*/
(
/* Return FALSE if character is beyond visible length of line. */
if (LineTable [Line].LineLength < 3 I I

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 443 .

Column > LineTable [Line].LineLength -3)


return FALSE;

/* Move all characters beyond deleted character one place left.


memmove
(LineBuffer + Column, /* Target.
LineBuffer + Column + 1, /* Source.
LineTable [Line].LineLength -Column -1) ; /* Number of bytes.
--LineTable [Line].LineLength;

return TRUE;

} /* end Deletechar */

void DeleteLine (SHORT Line)

Deletes the specified line ('Line' , which must be the line currently
containing the cursor) from the file buffer.
*/
If line to be deleted is the last file line, merely truncate it. */
(Line == LastLine)
(
LineBuffer [0] = '\n';
LineBuffer [1] = '\0';
LineTable [Line].LineLength = 2;
)
else
(
/* Place the following line into 'LineBuffer' .
GetTempBuf (Line + 1) ;

/* Move all LineTable elements beyond deleted line down one element*/
memmove
(&LineTable [Line] , /* Target.
&LineTable [Line + 1], /* Source.
(LastLine -Line) * sizeof (LineTable [0])) ; /* Number bytes
--LastLine ;
)

} /* end DeleteLine */

char *ErrorMessage (int ErrorNumber)


Returns a string that describes the error code given by 'ErrorNumber' .
(
static char *MessageTable [] =
(
''no error",
''file open failure",

• Figure 8.38..
The C source code file for the example program (continued)
• 444 Programmer's Guide to the os/2PresentationManager

''file too large",


''maximum lines exceeded",
"heap memory allocation failed",
''unidentif led error"
in
if (ErrorNumber >= sizeof (MessageTable) / sizeof (char *))
ErrorNumber = sizeof (MessageTable) / sizeof (char *) -1;
return MessageTable [ErrorNumber] ;

} /* end ErrorMessage */

PCH GetLineAddr (int Line)


/*
Returns the address of the file buffer line specified by 'Line' .
(
if (Line < 0 I I Line > LastLine)
return NULL;
else
return LineTable [Line].LineAddress;

} /* end GetLineAddr */

SHORT GetLineLength (int Line)


/*
Returns the length of the file buffer line specified by 'Line' .
(
if (Line < 0 I I Line > LastLine)
return 0;
else
return LineTable [Line].LineLength -2;

} /* end GetLineLength */

void GetTempBuf /* Places specified line into 'LineBuffer'.


(int Line) /* Number of line.
/*
This function:
o Copies the string in the specified line into 'LineBuffer'
o Frees the block formerly holding the string
o Adjusts the address in 'LineTable'
*/
(
/* Copy string into 'LineBuffer' .
movedata /* Intersegment block copy.*/
(SELECTOROF (LineTable[Line].LineAddress) , /* Source segment. */
OFFSETOF (LineTable[Line].LineAddress) , /* Source offset. */
Lineselector, /* Target segment. */
Lineoffset, /* Target offset. */

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 445 .

LineTable [Line] .LineLength) ; /* Bytes to copy.

/* Release block formerly holding line.


±f (WiEE::;¥em /* Handle of heap from 'WincreateHeap'.

(BYTE NEAR *)OFFSETOF (LineTable [Line].LineAddress) , /* Offset.


LineTable [Line].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message,"managing heap; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

LineTable [Line] .LineAddress = MAKEP (Lineselector,Lineoffset) ;

} /Jf end GetTempBuf */

int InsJ,ei-tchar /* Inserts character into 'LineBuffer


(SHORT Line, /* Number of line for insertion.
USHORT Character, /* Character to insert.
SF.,[ORT Column, /* Column position of character.
int Insert) /* Flag indicating overwrite mode.
(
unsigned char LineLength;
LineLength = LineTable [Line] .LineLength;

/* If line would exceed maximum line length, return without inserting. */


if (Column > LINEBUFSIZ - 3 I I LineLength >= LINEBUFSIZ && Insert)
return FALSE;

/* If column is at end of line (common case) , use fast routine to insert*/


else if (Column == LineLength -2)

;* Copy '\n' and '\0' to new position. */


IjineBuffer [Column + 2] = LineBuffer [Column + 1];
LineBuffer [Column + 1] = LineBuffer [Column];

LineBuffer [Column] = (char)Character; /* Write the character. */


++LineTable [Line].LineLength;
return TRUE;
)

/* If column is BEYOND end of line, must pad line with spaces. */


else if (Column > LineLength - 2)

;* Copy '\n' and '\O' to new position. */


LineBuffer [Column + 2] = LineBuffer [LineLength -1] ;
LineBuffer [Column + 1] = LineBuffer [LineLength -2];

/* Fill line with spaces. */


memset
(LineBuffer + LineLength -2, /* Destination. */

• Figure 8.38:
The C sou',rce code file for the example program (continued)
•446 Programmer's Guide to the OS/2 Presentation Manager

/* Character to fill with. */


Column -LineLength + 2); /* Number of repetitions. */
_

LineBuffer [Column] = (char)Character; /* Write the character. */

/* Adjust line length.


LineTable [Line].LineLength = (unsigned char)Column + 3;
return TRUE;
)
else /* Otherwise, must insert character in middle of line. */

/* If insert mode is active, move all characters right of */


/* insertion point one space to the right. */
if (Insert)
(
memmove /* Move block */
(LineBuffer + Column + 1, /* Target. */
LineBuffer + Column, /* Source. */
LineLength -Column); /* Number of bytes. */
++LineTable [Line].LineLength;
)
LineBuffer [Column] = (char)Character; /* Write the character. */
return TRUE;
)

} /* end Insertchar */

void InsertLine (SHORT Line, SHORT Column)


/*
Inserts a new line into the file buffer, immediately before character
given by 'Column' , within the line given by 'Line' .
(

:::HH:::B:i::::; /: ::::: ::=b::i:::: ::f:::; base.


/* Fatal error if maximum lines reached.
if (++LastLine >= MAXLINES)
(

::=:=::±tM::::::#?ximum lines reached; line %d", LINE_) ;


)

/* Adjust 'Column' to maximum position in line.


if (Column > LineTable [Line].LineLength -2)
Column = LineTable [Line].LineLength -2;

/* Allocate a block for characters in line before 'Column' .


Heapof fset = WinAllocMem
(HHeap,
Column + 2) ;
if (Heapof fset == NULL)

• Figure 8.38..
The C source code fr]e for the example program (continued)
DesigningDialogBoxes 447 .

(
sprintf (Message,"out of heap memory; line %d", LINE );
ErrorQuit (Message) ;
)

/* Copy characters before 'Column' into new block.


movedata /* Intersegment block copy.
( Lineselector , /* Source: selector of 'LineBuffer
Lineof fset , /* Source: offset of 'LineBuffer' .
Heapselector, /* Target: selector of heap.
(unsigned)Heapoffset /* Target: offset of new block.
Column) ; /* Number of characters to copy.
/* Construct a far pointer to new block in heap.
Heappointer = MAKEP (Heapselector,Heapoffset) ;

/* Write newline and null to end of new line in heap.


*(Heappointer + Column) = '\n';
*(Heappointer + Column + 1) = '\0' ;

/* Move character number 'Column' and all following characters to


4:in::3:nnin9 °f 'L±neBuffer'. /* |ntrasegment block copy
(LineBuffer, /* Target address.
LineBuffer + Column, /* Source address.
LineTable [Line].LineLength -Column) ; /* Bytes to move.

LineTable [Line] .LineLength -= (unsigned char)Column;

/* Move all members of 'LineTable' one position toward end of table.


memmove
(&LineTable [Line + 1], /* Target.
&LineTable [Line] , /* Source.
(LastLine -Line) * sizeof (LineTable [0])) ; /* Bytes to move.
/* Assign address of new heap block to 'LineTable' .
LineTable [Line] .LineAddress = Heappointer;
LineTable [Line] .LineLength = (unsigned char) (Column + 2) ;

} /* end InsertLine */

int JoinLine (SHORT Line)

Combines the line in the file buffer given by 'Line' with the previous
i ine .

Return if 'Line' is the first in the file (no previous line).


(Line -- 0)
return FALSE;

/* Return if combined length would exceed maximum line length. */


if (LineTable [Line].LineLength + LineTable [Line -1].LineLength -2 >
LINEBUFS I Z )

• Figure 8.38:
The C source code file for the example program (continued)
• 448 Programmer's Guide to the os/2PresentationManager

return FALSE;

/* Move existing characters in 'LineBuffer' to right to make room for


/* the characters from previous line.
memmove

i:i::::::::L:n:::::::::n::::: -L] . L±neLength/: N:iber/:f::i::::


/* Move the characters from previous line to beginning of 'LineBuffer' . */
movedata
(SELECTOROF (LineTable [Line -1].LineAddress) ,
OFFSETOF (LineTable [Line -1].LineAddress) ,
Lineselector ,
Lineo f f set ,
LineTable [Line -1] .LineLength -2) ;

/* Adjust line length for added characl:ers.


LineTable [Line].LineLength += LineTab:.e [Line -1].LineLength -2;

/* Free block used by previous line.


if (WinFreeMem
(HHeap, /* Handle of heap from 'WincreateHeap'.
(BYTE NEAR *)OFFSETOF (LineTable I Line-1] .LineAddress) , /* Offset.
LineTable [Line-1].LineLength) /* Length of block to free.
!-NULL)
(
sprintf (Message, "managing heap; line %d", LINE );
ErrorQuit (Message) ;
)

/* Move all 'LineTable' members above and including 'Line' down one */
/* place. */
memmove
(&LineTable [Line -1], /* I)estination. */
&LineTable [Line] , /* !5ource. */
(LastLine -Line + 1) * sizeof (LLneTable [0])); /* Bytes to move.*/
--LastLine ;

return TRUE;

} /* end ToinLine */

void NewFile (void)


/*
Initializes the file buffer for a new, empty file.
*/
(
PCH Farptr; /* Temporary far character pointer. */
LineBuffer [0] = '\n'; /* Initialize 'LineBuffer'. */
LineBuffer [1] = '\0';

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 449 .

/* Initialize 'LineTable' for first (and only) line.


LineTable [0].LineAddress = MAKEP (Lineselector, Lineoffset) ;
LineTable [0].LineLength = 2;

LastLine = 0;

/* Create a heap to hold data added to file.


H]ieap = WincreateHeap
(0, /* Segment address: 0 means allocate new segment.
4096, /* Initial heap size.
0, /* Minimum increase size: 0 means use default.
0, /* Minimum # of dedicated free lists: none.
0, /* Maximum # of dedicated free lists: none.
HM MOVEABLE); /* Options: support movable objects.

/k obtain selector address of heap.


Farptr = WinLockHeap (HHeap) ;
Heapselector = SELECTOROF (Farptr) ;

} /* end NewFile */

int ReadFile /* Reads file into editor.


(char *FileName) /* Name of file.
(
FILE *PtrFile; /* File stream pointer.
long FileLength; /* Size of file.
USHORT Heapsize; /* Size of allocated heap.
NPC]I Heapoffset; /* Offset of blocks within heap.
unsigned char LineLength; /* Length of lines.
PCH Farptr; /* Temporary far pointer.
if ((PtrFile = fopen (FileName,"r")) == NULL) /* Open file.
return (ERROPEN) ;

/* Get length of file.


iJi ((FileLength = filelength (fileno (PtrFile))) == -1)
return (ERROPEN) ;

i]: (FileLength > 50000) /* Test file length.


return (ERRTOOBIG) ;

/it Make heap 20% larger than size of file.


Heapsize = (USHORT) (FileLength + FileLength / 5) ;

HIIeap = WincreateHeap /* Allocate a heap.


(0, /* Segment address: 0 means allocate new segment.
Heapsize, /* Initial heap size.
0, /* Minimum increase size: 0 means use default.
0, /* Minimum # of dedicated free lists: none.
0, /* Maximum # of dedicated free lists: none.
0) /* Options: none.
Farptr = WinLockHeap (HHeap) ; /* Get far address of base of heap.
Heapselector = SELECTOROF (Farptr) ;/* Extract selector value.

• Figure 8.,38..
The C source code file for the example program (continued)
®450 Programmer's Guide to the OS/2 Pres(mtation Manager

LastLine = -1; /* Initialize index of last line.


while (fgets (LineBuffer,LINEBUFSIZ-1,I`trFile) != NULL)
(
if (++LastLine >= MAXLINES) /* Test limit of number of lines.
return (ERRMAXLINES) ;

LineLength = (unsigned char)strlen (LineBuffer) + 1;/* Include null*/


if `:i:::::::: i:I::E:E::g|: ;]|!::&,\n,, /: ::::::n;t:'|::::. :/
(
LineBuffer [LINEBUFSIZ -2] == '\n';
LineBuffer [LINEBUFSIZ -1] == '\0';
++LineLength ;
)

Heapoffset = WinAllocMem /* Allocate block from heap.


(HHeap, /* IIeap handle.
LineLength) ; /* ]uength of line to store.
if (Heapoffset == NULL) /* rJest for error.
return (ERRALLOC) ;

/* Copy line into heap block. */


movedata (Lineselector, Lineoffset ,Heapselector,
(unsigned) Heapof fset , LineLength) ;
/* Insert line information into the table. */
LineTable [LastLine] .LineAddress := MAKEP (Heapselector,Heapoffset) ;
LineTable [LastLine].LineLength = LineLength;
)

/* Place line 0 in working buffer.


GetTempBuf (0) ;

fclose (PtrFile) ; /* =lose the file.


return (0) ;

} /* end of ReadFile */

void ReleaseFile (void)


/*
Destroys the current heap, thereby freeing all file data.
*/
(
if (HHeap != NULL)
WinDestroyHeap (HHeap) ;

return ;
} /* end ReleaseFile */

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 451 .

void ReleaseTempBuf
(irlt Line) /* Number of line held in 'LineBuffer' .
/*
This function:
o Allocates a new block of memory just large enough to hold the string in
the 'LineBuffer'
o Copies the string into the new block
o Adjusts the address in 'LineTable'

(
NPCH Heapoffset; /* Offset of block within heap.

/* A].locate a block to hold current contents of 'LineBuffer' .


Heapoffset = WinAllocMem
(HHeap,
LineTable [Line] .LineLength) ;
if (Heapof fset == NULL)
(
sprintf (Message,"out of heap memory; line %d",_LINE_) ;
ErrorQuit (Message) ;
)

/* Cc>py characters from 'LineBuffer' into new block in heap.


movec.lata /* Intersegment block copy.
(Lineselector, /* Source: selector of line buffer
Lineoffset, /* Source: offset of line buffer.
Heapselector, /* Target: selector of heap.
(unsigned)Heapoffset, /* Target: offset of new block.
LineTable [Line] .LineLength) ; /* Bytes to copy.

/* Acljust address in 'LineTable' to point to new block.


LineTable [Line] .LineAddress = MAKEP (Heapselector, Heapoffset) ;

} /* end ReleaseTempBuf */

int SaveFile (char *FileName)


(
register int i; /* Loop counter.
FI1,E *PtrFile; /* File stream pointer.
char TempBuffer [LINEBUFSIZ] ; /* Temporary local buffer for lines.
PCH Farptr; /* Temporary far pointer.
unsigned Bufsel; /* Selector of 'TempBuf ' .
if ((PtrFile = fopen (FileName,"w")) == NULL) /* Open file.
return FALSE;
Farptr = (char far *)TempBuffer; /* Obtain selector for 'TempBuf'. */
Bufsel = SELECTOROF (Farptr) ;

/* Write file line by line. */


for (i = 0; i <= LastLine; ++i)
(
/* First copy line into a local buffer. */
movedata /* Block copy. */

• Figure 8.38..
The C source code file for the example program (continued)
• 452 Programmer's Guide to the os/2PresentationManager

(SELECTOROF (LineTable [i].LineAddress)


OFFSETOF (LineTable [i].LineAddress) ,
Bufsel ,
(unsigned int) TempBuffer,
LineTable [i] .LineLength) ;

/* Write line to file.


fputs (TempBuffer, PtrFile) ; /* Write a line to file.
)

fclose (PtrFile) ; /* Close file.


return TRUE;

} /* end SaveFile */

int SearchBuf (char *Findstring, PSHORT Lir]e, PSHORT Col)


/*
Searches f ile buf fer for string 'Findstring' , from position given by
'Line' and 'Column'. If string is found, updates 'Line' and 'Col' to
position immediately after the string in buffer, and returns TRUE. If
string is not found, function does not update 'Line' and 'Col', and it
returns FALSE.

(
register int i, j;
char far *Fptrch;
Fptrch = LineTable [*Line] .LineAddress, + *Col;
i - *Line;
for (;;)
(
while (*Fptrch)
(
for (j = 0; Findstring [j] =:= Fptrch [j] && Findstring [j]; ++j)

if (Findstfing [j] == '\0')


(
*Line -i;
*Col = Fptrch + j -LirieTable [i].LineAddress;
return TRUE;
)
++Fptrch ;
)
if (++i > LastLine)
return FALSE;
Fptrch LineTable [i].LineAddres;s;
)

} /* end SearchBuf */

/*** Utility functions. ******************t'***********************************/

• Figure 8.38..
The C source code file for the example program (continued)
DesigningDialogBoxes 453 .

V°±d ?:,=:=Q:::ssage) /* Te;¥±E:::rp::::::ed:: ::s:::;Lt:r:::r:°nd±tL°n.


(
char Buffer [60];

sprintf (Buffer,"Program Error: %s",Message) ;


WinMessageBox /* Display a message box.
(HWND DESKTOP, /* Handle of parent: desktop window.
HFrame , /* Handle of owner: frame window.
Buffer, /* Message text.
IupM Text Editor", /* Caption.
0, /* Help window ID: not needed.
MB OK I /* Display an 'OK' button.
MB-ICONHAND) ; /* Display a hand icon.

Quit (1); /* Call normal termination function.


} /* end ErrorQuit */

char *Extension (char *FileName)


Returns a pointer to the beginning of the extension contained in
`FileName' , or NULL if there is no extension.

(
while (*FileName)
if (*FileName++ == '.')
return (FileName) ;
return (FileName) ;

} /* end Extension */

void Getpath (char *Path, unsigned Pathsize)


Copies fully qualified path to 'Path' ; will not copy beyond the length of
'Path' given by Pathsize.

tsHORT DriveNumber; /* Disk drive number. */


ULONG LogicalDrives; /* Mapping of installed drives. */
*/
/* If target buffer is too small, return without altering it.
if (Pathsize < 3)
return ;
/* Obtain current default disk and mapping of installed drives.
DosQC!:i::::I::::::) ; /: ::::±¥:: ::::::g°:fc::::::i::±¥:ives.

/* Write drive letter to 'Path' .

• Figure 8.38..
The C source code file for the exanple program (continued)
• 454 Programmer's Guide to the os/2PrestmtationManager

sprintf (Path,"%c:\\",DriveNumber + 64i;

/* Adjust 'Pathsize' for drive specification.


Pathsize -= 3;

/* Obtain current default directory.


DosQCurDir
(DriveNumber, /* Drive numb3r: current drive.
Path + 3, /* Address of buffer to receive directory.
&(USHORT)Pathsize) ; /* Length of buffer to receive directory.

return ;
} /* end Getpath */

void Initwindow (void)


/*
This function initializes the window when a new file is read ('Open'
file menu item) , or when a new empty file is started ('New' file menu
item). It performs the following tasks:
o Initializes global cursor and window variables so that the cursor
is placed at the first character of the file, and the beginning of
the file is displayed in the window.
o Adjusts range and position of horizontal and vertical scroll bars.
o Positions the cursor at top left of window.
o Invalidates the entire window to fcirce displaying the new data.
*/
(
Cursorcol = CursorLine = 0;
TopLine = Firstcol = 0;
TopLineMax = max (0,LastLine -ywin / ycharTot + 1) ;
FirstcolMax = LINEBUFSIZ - 2 -xwin / xchar;
WinsendMsg /* Adjus;t range/position of slider.
(HVscroll, /* Reci|jient handle: vertical scroll bar.
SBM SETSCROLLBAR, /* Set I)osition & range.
MPFEOM2SHORT (TopLine, 0) , /* Position.
MPFROM2SHORT (0, TopLineMax) ) ; /* Range.

WinEnablewindow /* Enable scroll bar if scrolling is possible.


(HVscroll, /* Reci])lent handle (vertical scroll bar).
TopLineMax ? TRUE : FALSE) ; /* ]]nable only if max.

WinsendMsg /* Adju:5t range/position of slider.


(HHScroll, /* Reci])lent handle: horizontal scroll
SBM SETSCROLLBAR, /* Set position & range.
MPFkoM2SHORT (Firstcol, 0) , /* Position.
MPFROM2SHORT (0, FirstcolMax) ) ; /* Range.

if (Hclient == WinQueryFocus (HWND DESKTOP,FALSE) )


Wincreatecursor /* SEt =ursor position.
(Hclient,
(Cursorcol - Firstcol) * xchar,
ywin - (CursorLine - TopLine + 1) * ycharTot,
0'

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 455 .

0,
CURSOR SETPOS,
NULL) ;

WirilnvalidateRect /* Invalidate entire window.


(Hclient, /* Client window handle.
0' /* Rectangle: 0 means whole window.
FALSE) ; /* Do not automatically include children
} /* end Initwindow */

void Qualify (char *Unqual, char *Qual)


/*
Conve.rts file name 'Unqual' (either a simple or qualified file name) to
a fully qualified file name, which includes the drive specification and
full directory path, and is copied to 'Qual' .
*/
(
char PathBuffer [PATHLENGTH] ;
char *Ptrpath = PathBuffer;
Getpath (PathBuffer, sizeof (PathBuffer) ) ;
if (*(Unqual + 1) == I:I)
(
*Qual++ = *Unqual++;
*Qual++ = *Unqual++;
Ptrpath +-2;
)
else
(
*Qual++ = *Ptrpath++;
*Qual++ = *Ptrpath++;
)
if (*Unqual !-'\\')
(
while (*Qual++ = *Ptrpath++)

if (*(Qual -2) --'\\')


--Qual ;
else
*(Qual -1) -'\\';
)

whi.Le (*Qual++ = *Unqual++)

} /* end Qualify */

void Quit: (int Errorcode)


/*
Gal:Ls Presentation Manager termination functions and ends program
with iEermination status given by 'Errorcode' .

• Figure 8.38..
The C source code file for the example program (continued)
• 456 Programmer's Guide to the os/2 Pres9ntationManager

*/
(
USHORT Reply; /* Response from message box. */

/*** If buffer is modified, query user whether to save file. *****************/


if (Modif led)
(
Reply = WinMessageBox
(HWND DESKTOP,
Hcliefit'
"File unsaved; Save?",
"PM Text Editor",
0'
MB_YESNO I
MB ICONQUESTION) ;

/* If reply is Yes, send a 'Save' menu message to client.


if (Reply == MBID YES)
while (Modified)
WinsendMsg
(Hclient, /* Client window handle.
WM COMMAND, /* Menu message.
MPFROM2SHORT (ID SAVE, 0) ,/* Command for 'Save' item*/
OL); /* mp2: not used
)

if (HHeap != NULL)
WinDestroyHeap (HHeap) ;
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue)
WinTerminate (HAncBlk) ;
exit (Errorcode) ;

) /* end Quit */

void ShowFileName (void)


/*
Updates the text in the title bar to show the current file name.
*/
(
/* Format title.
sprintf (Title, ''PM Editor -%s", FileName[0] ? Unqualify (FileName)
: „(untitled)„);

/* Modify the title bar window text.


WinsetwindowText
(HFrame, /* Window handle: frame routes text to menu.
Title) ; /* String containing the text.
) /* end ShowFileName */

char *Unqualify (char *Qual)


/*

• Figure 8.38..
The C source code file for the exanple program (continued)
DesigningDialogBoxes 457 .

Returns a pointer to the simple file name within the string 'Qual' ,
which contains a partially or fully specified file path. Converts the
unqualified f ile name to uppercase.

(
char *Ptrch;
Ptrch = Qual + strlen (Qual) ;

while (Ptrch
* ( Ptrch-.1 )
* ( Ptrch-.1 )
--Ptrch ;
Winupper /* Convert unqualified name to uppercase.
(HAncBlk, /* Anchor block handle.
NULL, /* Code page: use current.
NULL, /* Country code: use default.
Ptrch) ; /* Address of string to be converted.
return (Ptrch) ;

} /* end Unqualify */

• Figure 8.38..
The C source code file for the example program (continued)
PART

Advanced
Features
J pter nine

Inter facing witfi


th ClipBoard
461.

he clipboard is a Presentation Manager facility for trans-

.T
ferring data. Once an application has placed a block of
data into the clipboard, the data can be accessed by the
same application, or by any other program running
within a Presentation Manager window. The clipboard thus provides a
single, convenient mechanism for moving blocks of data within a pro-
gram, and for effecting data exchange among separate applications.
In this chapter you will learn how to place data into the clipboard,
and how to access data contained in the clipboard; you will learn how
to use the clipboard to implement commands for cutting, copying, and
pasting data within a single program or among separate applications;
and you will learn how to add a clipboard interface to the example pro-
gram developed in the first part of the book. The chapter focuses on the
basic methods for exchanging data in a standard text format; the last
section, however, introduces some of the advanced features of the
Presentation Manager clipboard, and includes a discussion of alterna-
tive data formats.

• ADDING DATATO THE CLIPBOARD


An application can place a block of data into the clipboard at any
time. Normally, however, data are inserted into the clipboard in
response to a command issued by the user. Presentation Manager
programstypicallyprovidecommandsforselectingablockofdata,and
then copying or cutting (that is, removing) this data selection and ad-
ding it to the clipboard. The section on Implementing a Clipboard Inter-
face, later in the chapter, discusses the menu commands that initiate
these operations and the techniques for marking a data selection. This
section assumes that a block of data is already available and describes
the procedure for actually inserting this block into the clipboard.
Note that the clipboard is a global Presentation Manager resource,
available to any program running within a Presentation Manager win-
dow. Since the data your program places into the clipboard may be
removed by another application, you must designate the data format so
that an arbitrary receiving application can determine whether it can
process the data. Note also that the clipboard can hold only a single
data selection at a given time; therefore, when your program adds a
• 462 Programmer's Guide to the os/2 PresentationManager

block of data, the previous clipboard contents are destroyed. (More ac-
curately, the clipboard can contain only a single block of data in a given
format; the clipboard can hold several blocks of data, as long as each
block has a distinct format. This feature allows an application to insert
the sfl777c data selection in several different formats so that the data can
be used by a greater variety of receiving applications.) This section
describes the methods for adding blocks of data that conform to the
standard fcxf format.
The fonowing are the five basic steps that an apphcation must perform
to add a block of textual data to the Presentation Manager clipboard:

1. Allocate a sharable memory segment.


2. Copy thedata into this segment.
3. Opentheclipboard.
4. Add the data segmentto the clipboard.
5. Closetheclipboard.

Allocate a Memory Segment


The Presentation Manager clipboard facility does 7iof provide the
actual memory for holding the data that are placed into the clipboard;
rather, it maintains only the flddrcsscs of the blocks of data. Your pro-
gram must explicitly allocate a memory segment from the operating
system to hold any block of data that it submits to the clipboard. Fur-
thermore, since this data segment may be accessed by another process,
the memory segment must be designated as s7t#r¢Z7Jc.
To allocate a shared memory segment suitable for holding a block of
clipboard data, you can call the OS/2 kernel function DosAllocseg.
This function is explained in Figure 9.1, and should be called as in the
following example:

USHORT Selectionsize,.
SEL SelclipData,.
Interfacingwiththeclipboard 463 .

DosAllocseg
( Selectionsi ze ,
&SelclipData,
SEG GETTanl.E) ,.

The first parameter in this example specifies the length of the segment
in bytes. You should request a segment large enough to hold the data
selection that is to be inserted into the clipboard (in this example, the
variable Selectionsize has presumably been assigned the number of
bytes in the current data selection). The second parameter supplies the
address of the variable that is to receive the segment selector. The final
parameter passes the flag SEG_GETTABLE, which specifies that the
segment is to be shared through the DosGetseg OS/2 function, which
will be explained in the section on Accessing Data in the Clipboard,
later in the chapter.
Note that your application does not have to free the segment contain-
ing the clipboard data. Rather, the Presentation Manager automatically
frees this segment (by calling DosFreeseg) when the clipboard data are
replaced through a subsequent data submission or are explicitly cleared
by means of the WinEmptyclipbrd Presentation Manager function
(Figure 9.6, discussed later in the chapter).
Note also that when allocating a segment for the clipboard, you
should call DosAllocseg rather than DosAllocshrseg. Both of these
functions can be used to obtain shared memory segments. DosAlloc-
Shrseg, however, provides a 77¢771cd shared memory segment, which
another process cannot access unless it knows the segment name. Dos-
Allocseg, on the other hand, provides what is termed a gz.zJc¢zu¢y shared
memory segment; the Presentation Manager clipboard can grant access
to this type of segment to another process by simply passing it the seg-
ment selector. (See the section on Accessing Data in the Clipboard for
details on how the second process obtains segment access once it has
received the selector.)

Copy the Data


Once you have allocated a segment to hold the clipboard data, the
next task is to copy the selected data into this segment. As you copy
the data selection into the sharable segment, you may have to modify it
®464 Programmer's Guide to the OS/2 Presentation Manager

DosAllocseg
Purpose,
Allocates a memory segment.

Prototype..
USHORT APIENTRY DosAllocseg
(USHORT ussize, The size of the segment in bytes (from
0 to 65,535; the value 0 allocates a
65,536-byte segment).
PSEL psel, Address of the variable to receive the
segment selector.
USHORT fAlloc) ,. The allocation flags, which can be a
combination of one or more of the
following values:

Value Effect
0 Creates a nonsharable,
nondiscardable segment
SEG GIVEABLE Calling process can call
DosGiveseg to obtain
a selector that can be
used by another
process to access the
Segment
SEG GETABLE Another process can
obtain access to the
segment by passing the
selector (psel) to the
DosGetseg function
SEG DISCARDABLE Creates a discardable
Segment

• Figure 9.1..
The DosAIlocseg OS/2 kernel function
Interfacingwiththeclipboard 465 .

Return Value ..
Returns 0 if the function is successful, or the value
ERROR NOT ENOUGH MEMORY if insufficient memory
isavaila-bletoiillthealloc-ationrequest.

Notes..
The segment can be freed by calling the DosFreeseg function.

Relate d Functions ..
DosFreeseg (Figure 10.27)
DosGetseg (Figure 9.7)

• Figure 9.1..
The DosA;Ilocseg OS|2 kernel function (continued)

to conform to the specified data format. (The format is specified when


the segment is submitted to the clipboard; this process is described later
in the chapter.) If the data selection conforms to the standard text for-
mat, it should be copied into the sharable segment observing the fol-
lowing conventions:

• Each line should end with a carriage-return ('\r') and line feed
('\n') combination. Note that C programs typically use only the
' \n' character to terminate individual lines within textual data;

you may therefore have to insert accompanying '\r' characters


as the data are copied into the sharable segment.
• The tab character ('\t') canbe used to separate data fields within
a single line.
• The entire data block is terminated with a single NULL character
(,\0,).

According to these conventions, the data block consists of a single


NULL-terminated string, which may contain one or more lines of text.
• 466 Progranmer's Guide to the os/2PresentationManager

As an example, the following code copies a block of data into a memory


segment allocated for the clipboard:

char far *Ptrselection,.


SEL SelclipData,.
unsigned int DataLength,.

movedata
(SELECTOROF (Ptrselection) , /* Source selector.
OFFSETOF (Ptrselection) , /* Source offset.
SelclipData, /* Target selector.
0, /* Target offset.
DataLength) ,. /* Bytes to copy.

This example uses the C library function movedata, which copies data
from one segment to another. Note that it does not perform data trans-
lation; it assumes that the data are already in the proper format. This ex-
ample also assumes that Ptrselection has been assigned the far address
of the data selection within the program, that SelclipData contains the
selector of the sharable segment supplied by DosAllocseg, and that
DataLength has been assigned the number of bytes contained in the
data selection that is to be copied into the sharable segment.

Open the Clipboard


Before an application can access the clipboard (either to add or to
obtain a data block), it must call the Presentation Manager function
Winopenclipbrd (Figure 9.2) to open the clipboard for the current pro-
gram thread. The purpose of this function is to grant the program ex-
clusive access to the clipboard data, thereby preventing conflicts among
separate applications that are using the clipboard. Once your applica-
tion has opened the clipboard through Winopenclipbrd, no other pro-
gram may open it until your application calls Wincloseclipbrd
(explained later) to close the clipboard. If another program calls Win-
Openclipbrd after your application has opened the clipboard, this
function docs 71o£ 7igf#7'71 until your application has closed the clipboard.
Interfacingwiththeclipboard 467 .

Therefore, holding an open clipboard may block other programs; ac-


cordingly, you should close the clipboard as soon as possible (for ex-
ample, allocate the sharable segment and copy the data into this
segment Z7e/ore opening the clipboard).
The following example illustrates the use of Winopenclipbrd:

HAB mcBlk,.

Winopenclipbrd
(HmcBlk) ,. /* Anchor block handle.

Winopenclipbrd
Purpose..
Opens the clipboard for the current thread, to provide this
thread exclusive access to the clipboard.

Prototype..
BOOL APIENTRY Winopenclipbrd
(HAB hab) ,. Anchor block handle.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
If another thread already has the clipboard open, this func-
tion does not return until this thread has closed the clip-
board. The clipboard is closed by calling Wincloseclipbrd.

Related Functions ..
Wincloseclipbrd (Figure 9.4)

• Figure9.2..
The Winopenclipbrd Presentation Manager function
• 468 Programmer's Guide to the os/2 PresentationManager

The value HAncBlk, passed as the parameter to Winopenclipbrd, is


the anchor block handle returned by the call to Winlnitialize (Figure
2.2) issued at the beginning of the Presentation Manager application.

Insert the Data


Segment into the Clipboard
Once you have opened the clipboard, you can place the sharable
segment within the clipboard by calling the WinsetclipbrdData
Presentation Manager function (Figure 9.3). When you add a block of
data to the clipboard with this function, you must specify the data for-
mat; these data replace any block of data having the same format that is
already in the clipboard. When adding a block of standard textual data
to the clipboard, you should call WinsetclipbrdData, as in the follow-
ing example:

HAB ELincBlk,.
SEL SelclipData,.

WinsetclipbrdData
(rmcBlk,
(ULONG)MAKEP (SelclipData, 0) ,
CF TEXT,
0),.

The first parameter passed to this function is the anchor block handle
returned by the call to Winlnitialize. The expression passed as the
second parameter generates a far pointer to the base of the sharable seg-
ment that was allocated through DosAllocseg. (DosAllocseg assigns
the segment selector to SelclipData, which is combined here with a 0
offset.) The third parameter specifies the data format; the value
CF_TEXT indicates the standard text format that was described earlier
in the chapter (in the section entitled Copy the Data). Note that the data
format is stored in the clipboard along with the data address; as you
Interfacingwiththeclipboard 469 .

WinsetclipbrdData
Purpose..
Places a block of data into the clipboard.

Prototype..
BOOL APIENTRY WinsetclipbrdData
(ELne hab, Anchor block handle.
ULONG ulData, Handle to the block of data to be
inserted into the clipboard. If the data
is formatted as text, this parameter
supplies the far address of the base of
the sharable segment containing the
data; if the data is a bitmap or metafile,
this parameter contains the handle to
the object. Passing a value of NULL
indicates that the clipboard owner will
delay rendering the data until it
receives a WM RENDERFMT message.
USHORT fmt, Format of the data; you can specify a
private format or one of the following
predefined formats:

Identifier Format
CF TEXT Standard text format
CF BITMAP Bitmap format
CF METAFILE Metafile format
CF DSPTEXT Text display format
associated with a
private format
CF DSPBITMAP Bitmap display format
associated with a
private format

• Figure 9.3..
The WinsetalpbrdD ataL Presentation Manager function
•470 Programmer's Guide to the OS/2 Presentation Manager

USHORT rgfFmtlnfo ) ,. Information on the data block referenced


by the parameter ulData. You can
specify a memory model and a usage
flag from the following values (you can
select 0 or 1 memory model, and 0,1, or
2 usage models; values are combined
with the bitwise OR operator):

Memory Model Meaning


CFI SELECTOR TheparaneterulData
contains a segment
selector combined with
a 0 offset
CFI HANDLE The parameter ulData
is the handle of a
bitmap or a metafile

Usage Flag Meaning


CFI OINERFREE The handle is not
automatically freed by
the system; the
clipboard owner must
explicitly free the
handle in response to
the VVM DESTROY-
CLIPBOARD message
CFI OWNER- The clipboard owner
DISPLAY will display the
contents of the
clipboard within the
viewer window in
response to the
WM PAINTCLIPBOARD
message (ulData
should be NULL)

• Figure 9.3..
The WinsetcILpbrdD ataL Presentation Manager function ( continued)
Interfacingwiththeclipboard 471 .

Return Value ..
TRUE if the data was placed into the clipboard, or FALSE if
the data was not added to the clipboard (either because of an
error, or because the handle ulData was NULL).

Notes..
If you specify a predefined data format (text, bitmap, or
metafile), you do not need to assign a memory model
through the rgfFmtlnfo parameter.

Related Functions ..
WinQueryclipbrdData (Figure 9.5)

• Figure 9.3..
Tire WLnsetcILpbrdData Presentation Manager f unction ( continued)

will see, when a program accesses data within the clipboard, it must re-
quest a specific data format. (Formats other than text are listed in the
last section of the chapter.)
The last parameter supplies additional information concerning the
block of data specified by the second parameter. When submitting data
in the standard text format, you do not need to specify any of the values
that may be passed through this parameter. (Some of the possible
values for this parameter listed in Figure 9.3 are described in the last
section of the chapter.)
Note that once your program has called WinsetclipbrdData to sub-
mit the address of the shared data segment to the system, it should no
longerusethisaddress.Rather,ifyourprogramrequiressubsequentaccess
to the block of data, it should fouow the standard procedures for accessing
datawithinthechpboard,deseribedlaterinthechapter.(Databelongingto
the chpboard must be accessed through the system so that at a given time
only one program thread can add, read, or remove data. Also, the system
may have freed the original segment selector passed to Winsetclipbrd-
Data; using such a selector will generate a protection fault.)
• 472 Programmer's Guide to the os/2 Presentation
Manager

Close the Clipboard


After the data segment has been placed in the clipboard, the pro-
gram should call Wincloseclipbrd (Figure 9.4) to relinquish its ex-
clusive access to the clipboard. As mentioned previously, you should
call this function as soon as possible to minimize the amount of time
any other applications attempting to open the clipboard are blocked.

Wincloseclipbrd
Purpose..
Closes the clipboard, previously opened through Winopen-
Clipbrd.

Prototype..
BOOL APIENTRY Wincloseclipbrd
(HAB hab) ,. Anchor block handle.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
By calling this function, an application relinquishes its ex-
clusive access to the clipboard, and other applications are
free to open the clipboard.

RelatedFunctions..
Winopenclipbrd (Figure 9.2)

• Figure 9.4..
The Wincloseaipbrd Presentation Manager function
Interfacingwiththeclipboard 473 .

ThefollowingisanexampleofacautotheWincloseclipbrdfunction:

HAB ELincBlk,.

Wincloseclipbrd
(-cBlk) ,.

ACCESSING DATA
IN THE CLIPBOARD
This section describes the techniques for obtaining a block of data
from the clipboard. A program typicauy requests data from the cupboard
inresponsetoapastecommandissuedbytheuser(thatis,acommandto
copy a block of data from the clipboard and insert it into the data main-
tained by the program). When requesting a block of data, your program
mustspecifyaparticularformat;ifthechpboardcontainsablockthatcon-
forms to this format, it will supply the data handle (in the case of textual
data, the handle is the far address of the segment holding the data). The
blockthatthesystemprovidesistheonewiththerequisiteformatthathas
most recently been added to the cupboard (remember that the cupboard
maintainsonlyasingleblockinagivenformat).Thisblockmayhavebeen
placed in the clipboard by your program, or by another Presentation
Manager apphcation. This section describes the methods for accessing
blocks of data that conform to the standard fcxf format.
Note that obtaining a block of data from the clipboard merely allows
your program to read or copy this block; it does 71of remove it from the
clipboard. Therefore, the same block can be repeatedly accessed. (The
block is not removed until another block with the same format is added,
or a program calls WinEmptyclipbrd, described later in Figure 9.6.)
The following five steps can be used to access a block of textual data
contained in the clipboard:

1. Opentheclipboard.
2. Obtainthe address of theblock.
• 474 Programmer's Guide to the os/2PresentationManager

3. Secure access to the shared memory segment.


4. Process orcopytheblock.
5. Closetheclipboard.

Open the Clipboard


Your program must call Winopenclipbrd (Figure 9.2) to open the
clipboard before accessing a data block, just as it must open the clip-
board prior to adding a block. This function was described in the sec-
tion on Adding Data to the Clipboard, and it is called as follows:

RE rmcBlk,.

Winopenclipbrd
(HAncBlk) ,. /* Anchor block handle. */

Obtain the Address of the Block


To obtain access to a block of data in the clipboard, you should call
the WinQueryclipbrdData Presentation Manager function (Figure 9.5),
specifying the desired data format. If the clipboard currently contains a
block with the requested format, WinQueryclipbrdData returns a
handle to this data; if the clipboard does 71of contain such a block, the
function returns NULL. If the data is in the text format, the handle con-
sists of the far pointer (that is, the selector and offset) of the segment
containing the data.
The following call to WinQueryclipbrdData requests a data block in
text format:

PCH PtrData,.
HAB ELincBlk,.
Interfacingwiththeclipboard 475 .

PtrData = (PCH) WinQueryclipbrdData


(ELincBlk,
CF TEXT) ,.
if (PtrData != NULL)
/* then you can process the data. . . */

As mentioned previously, calling WinQueryclipbrdData merely al-


lows your program to read or copy the data block, but does not remove
the block from the clipboard. If you want to eliminate a block from the
clipboard, you should call the Presentation Manager function Win-
Emptyclipbrd, described in Figure 9.6.

WinQueryclipbrdData
Purpose..
Returns a handle to the block of data in the clipboard that
has the requested format.

Prototype..
ULONG APIENTRY WinQueryclipbrdData
(HAB hab, Anchor block handle.
USHORT fmt) ,. Desired data format (see Figure 9.3 for a list
of the predefined formats).

Return Value ..
Handle to the data block having the requested format, or
NULL if the clipboard does not contain a block with this for-
mat or if an error occurred. If the block is in text format, the
handle is the far address of the memory segment containing
the data.

Relate d Functions ..
WinsetclipbrdData (Figure 9.3)

• Figure9.5..
The WinQuerycILpbrdDataL Presentation Manager function
• 476 Programmer's Guide to the os/2PresentationManager

WinEmptyclipbrd
Purpose,
Removes all data blocks from the clipboard, freeing the as-
sociated data handles.

Prototype..
BOOL APIENTRY WinEmptyclipbrd
(IIAB hab) ,. Anchor block handle.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

• Figure 9.6..
The WLnE"ptyc1±pbrd Presentation Manager function

Secure Access
to the Shared Memory Segment
If the handle returned by WinQueryclipbrdData is not NULL,
the next step is to call DosGetseg (Figure 9.7) to secure access for the
current process to the segment containing the clipboard data. Although
WinQueryclipbrdData returns a far pointer to this segment, this ad-
dress may have been supplied by ¢7ioffecr p7'occss (which would be the
case if the data in the clipboard were inserted by ¢7ioffecr application).
Even though the other process may have allocated the memory block as
a sharable segment (by passing DosAllocseg the SEG_GETABLE flag),
the selector portion of this address is not automatically valid within the
current process. Before using this selection, your program must call
DosGetseg to make the selector valid within the current process.
The following is an example of a call to DosGetseg:

PCH PtrData,.
Interfacingwiththeclipboard 477 .

DosGetseg
(SELECTOROF (PtrData) ) ,.

This example assumes that PtrData contains the far pointer to the clip-
board data returned by WinQueryclipbrdData; note that only the
selector portion is passed to DosGetseg. After calling this function, the
program may safely use PtrData to access the clipboard data.

DosGetseg
Purpose..
•Secures access to a shared memory segment for the current
process.

Prototype..
USHORT APIENTRY DosGetseg
(SEL sel) ,. The selector of the shared memory segment.

Return Value ..
Zero if the function was successful, or a nonzero error code if
the function failed.

Notes..
A selector to a shared memory segment obtained from Dos-
Allocseg can be passed to a second process. The second
process, however, must call DosGetseg before it can use this
selector. The call to DosAllocseg must have included the
SEG_GETABLE allocation flag in the third parameter.

Related Functions ..
DosAllocseg (Figure 9.1)

• Figure9.7..
The DosGetseg os/2 kernel function
®478 Programmer's Guide to the OS/2 Presentation Manager

A fecfe7iz.c¢J 77ofc.. The selector that a process obtains from DosAllocseg


istheindexofasegmentdescriptorwithintheprocess'slocaldescriptor
table. Since each process owns a distinct local descriptor table, this
selector is initially valid only within the process that called DosAlloc-
Seg. When a second process passes the selector to DosGetseg, how-
ever, the system places a new descriptor in the local descriptor table
belonging to the second process. This new descriptor is indexed by the
same selector, and it describes the same memory segment as the de-
scriptor belonging to the first process. Therefore, ¢cr calling DosGet-
Seg, the second process can use the selector to access the shared
segment. See the section in Chapter 1 on Virtual Memory.

Process or Copy the Block


Once your application holds a valid selector to the clipboard data,
it should process these data quickly and then close the clipboard. If the
application needs to retain the data, it should copy the block into a local
buffer, where it can perform the required processing at its leisure. Rapid
processing is important because, as explained previously, the clipboard
should be closed as soon as possible. Once the clipboard is closed, how-
ever, the application cannot use the segment selector obtained from the
clipboard; the sharable clipboard segment is therefore available for a
limited amount of time.
An application such as the text editor presented in the first part of
this book should copy the clipboard data directly into the buffer hold-
ing the file data; it should then close the clipboard before updating the
window display.

Close the Clipboard


After your application has finished processing or copying the clip-
board data, it should call Wincloseclipbrd (Figure 9.4) to relinquish its
exclusive access to the clipboard. After calling Wincloseclipbrd, the
program must not attempt to use the selector obtained from WinQuery-
ClipbrdData to access the clipboard data. (Remember that a similar
restriction was imposed when ¢ddz.7ig data to the clipboard.)
Interfacingwiththeclipboard 479 .

IMPLEMENTING
• A CLIPBOARD INTERFACE
The first sections in this chapter have described the basic Presenta-
tion Manager facilities that allow a program to insert a data selection
into the clipboard or to obtain the data selection that is currently con-
tained in the clipboard. This section describes a typical program inter-
face that permits the user to access these underlying facilities, and offers
suggestions for using the clipboard within the text editor example pro-
gram that was presented in the first part of the book. The user interface
described in this section follows the recommended style guidelines (as
described in the Microsoft Windows AppJ£.c¢f}.o7i SfyJc G%2.de, cited in the
Bibliography). Note that this section focuses on the techniques for
selecting and exchanging fcxf #¢J data (as opposed to graphical data; the
last section in this chapter briefly discusses nontext formats).
In a Presentation Manager application such as a text editor, there is a
one-to-one correspondence between the block of data contained in the
clipboard and the current program seJec£2.o71. The selection is a section of
data chosen by the user and typically highlighted within the window
display; at a given time, there may or may not be a selected block of
data. When the user requests a ct/i clipboard operation, the selected
data are copied to the clipboard and removed from the program. A copy
operation copies the selected data into the clipboard but leaves the data
within the program. A p¢sfc command copies the contents of the clip-
board into the program data; if a block of program data is currently
selected, the block of data copied from the clipboard typically replaces
the program selection. Finally, a cJc¢r operation deletes the selection
from the program but does not add the data to the clipboard. Concep-
tually, the clipboard stores a single program selection (although it can
actually maintain several blocks of data that have distinct formats).
Accordingly, the first step in implementing a clipboard interface is to
provide a mechanism for selecting a block of data and for highlighting
the selection within the window display. In a program such as a text
editor, the user should be able to make a data selection using either the
keyboard or the mouse. The recommended keystroke for extending a
selection is the Shift key in combination with one of the four arrow
keys; with the Shift key held down, an arrow key extends the selection
in the corresponding direction. You can process these keystrokes in the
®480 Programmer's Guide to the OS/2 Presentation Manager

routine that handles WM_CHAR messages. As the selection is ex-


tended, its dimensions should be maintained in global variables that
can subsequently be accessed by the routine that highlights the selected
text in the window display and by the routine that executes the clip-
board operations. The mouse interface for marking a selection is
described in Chapter 11. Note that in addition to allowing the user to
extend the selection character-by-character in any direction, a full-fea-
tured text editor or word processor should provide keyboard and
mouse commands for selecting entire words or lines.
For each keystroke that alters the current selection, the window pro-
cedure should execute a routine to update the highlighted area that
marks the current selection within the window. This routine can alter
the highlighting of a block of characters on the screen (either highlight-
ing the characters or removing the highlighting) by setting the back-
ground and foreground colors and then redrawing the characters using
the GpicharstringAt function (Figure 3.28). The following list sum-
marizes the basic steps:

• Obtain a presentation space by calling winGetps (Figure 3.19).


• Set the current character fontas described in chapter3.
• Hide the cursor by calling winshowcursor (Figure 5.5), passing
a value of FALSE as the second parameter.
• Call the function GpisetBackMix (Figure 9.8), passing the value
BM_OVERPAINT as the second parameter to force Gpichar-
StringAt to overwrite the current background color.
• Set the background color to blackby calling GpisetBackcolor
(Figure 9.9), passing the value CLR_BLACK as the second
parameter (or set it to white by passing CLR_WHITE to remove
the highlighting and restore the normal character colors).
• Set the foreground color to white by calling Gpisetcolor (Figure
3.29), passing the value CLR_WHITE as the second parameter
(or set it to black by passing CLR_BLACK to remove the high-
lighting and restore the normal character colors).
• Use the function GpicharstringAt to reprint the selected charac-
ters using the newly designated colors.
Interfacingwiththeclipboard 481 .

GpisetBackMix
Purpose..
Specifies the way the background color generated by
graphics functions (such as GpicharstringAt) is combined
with the existing color within the presentation space.

Prototype..
BOOL APIENTRY GpisetBackMix
(Hps hps , Handle to the presentation space.
LONG IMixMode) ,. The mode, which can be one of the following
values:

Value Effect
BM DEFAULT The default value
(same as
BM LEAVEALONE)
BMOR The pixel colors are
combined using the OR
operator
BM OVERPAINT The object background
color replaces the
existing color
BM XOR The pixel colors are
combined using the
exclusive-OR operator
BM LEAVE- The existing color in
AL6NE the background areas is
left unaltered (the
default)

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Related Functions ..
GpicharstringAt (Figure 3.28)
GpisetBackcolor (Figure 9.9)

• Figure 9.8..
The Gp±SetBaLck:MLx Presentation Manager f unction
• 482 Programmer's Guide to the os/2 PresentationManager

GpisetBackcolor
Purpose..
Sets the background color generated by graphics functions
such as GpicharstringAt.

Prototype..
BOOL APIENTRY GpisetBackcolor
(Hps hps , Handle to the presentation space.
LONG IColor) ,. The color value; the following basic
colors can be specified:
CLR WHITE
CLR-BLACK
CLR-BLUE
CLR-RED
CLR_PINK
CLR-GREEN
CLR-CYAN
CLR-YELLOW

Altematively, you can specify one of


the following identifiers :
Identifier Meaning
CLR BACKGROUND Default window color
CLR NEUTRAL Default foreground
color

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
If the mode set by GpisetBackMix is BM_LEAVEALONE
(the default), the background color set by this function will
not be drawn.

Relate d Functions ..
GpicharstringAt (Figure 3.28)
GpisetBackMix (Figure 9.8)

• Figure 9.9..
The Gp±SetBaLckcchor Presentation Manager function
Interfacingwiththeclipboard 483 .

• Restore the cursor visibility by calling winshowcursor, passing


a value of TRUE as the second parameter.
• Call winReleaseps (Figure 3.22) to release the presentation
Space.

See also the section in Chapter 6 on Enhancements for more informa-


tion on using the functions mentioned in this list.
The clipboard commands are normally accessed through a Presenta-
tion Manager submenu entitled Edit. Each of the commands within this
submenu typically has an associated accelerator key that allows the
user to quickly execute the command without going through the menu.
Table 9.1 summarizes these commands.

• Table 9.1.. Edit Menu Commands

Menu Menu Accelerator Action


Command Mnemonic Key
Cutt Shift-Del Copies selection
to the clipboard
and deletes
selected text from
Program
Copy C Ctrl-Ins Copies selection
to the clipboard
and leaves
selected text in
Program
Paste P Shift-Ins Copies current
contents of the
clipboard into the
program data
Clear I Del Deletes selection
from program
without adding it
to the clipboard
• 484 Programmer's Guide to the os/2 PresentationManager

In the table, the 777c7it/ co777777¢7id is the suggested label that appears in
the Edit pull-down submenu. The 777c71t/ 77771c777o713.c is the recommended
underlined letter within this label that can be used to quickly select the
associated command once the Edit submenu is displayed. The table also
gives the recommended accelerator keystrokes for each command; the
menu should display each of these keystrokes next to the associated
menu item.
The menu added to the example program in Chapter 7 includes an
Edit submenu with items for the Cut, Copy, and Paste commands. This
submenu is illustrated in Figure 9.10. Remember that the client window
receives a WM_COMMAND message, accompanied by the identifier of
the menu item, whenever the user selects one of these menu items or
presses the associated accelerator key. The final version of the example
program processes each of these messages by simply displaying a mes-
sage informing the user that the command has not been implemented.
You can fully implement each of these three commands using the tech-
niques presented in this chapter and in the first part of the book.
To execute the Copy command, you could add a function to the buff-
er-management module to copy the selected data directly from the
Presentation Manager heap into the sharable segment allocated for
the clipboard. The routine for the Cut command could begin by calling

• Figure 9.10:
The Edit submenu of the example program
Interfacingwiththeclipboard 485 .

this same function, and then call another buffer-management function


for deleting the current selection from the heap. The Paste routine could
call a third additional buffer-management function to copy the data
from the sharable segment obtained from the clipboard, and insert
these data directly into the heap. Finally, after closing the clipboard, the
routines for the Cut and Paste commands should call Winlnvalidate-
Rect to invalidate the entire client window, and then call Winupdate-
Window to force the WM_PAINT routine to properly display the newly
modified file data.
Note that adding a clipboard interface to the text editor would allow
the user to transfer data between separate instances of this program
running in distinct windows. Thus, the user can load different files into
separate program instances and have a program that acts like a stand-
ard editor that opens multiple files and provides cutting and pasting of
data among these files. (Remember that additiona.I program instances
load quickly because the code segments are already present in memory,
and consume a moderate amount of memory because these code seg-
rr\er\ts aLre shared.)

OTHER FEATURES
• OFTHECLIPB0ARD
This section briefly introduces the following three additional fea-
tures of the Presentation Manager clipboard facility:

• Alternative clipboard formats


• Theclipboard viewerwindow
• Delayed rendering of clipboard data

Note that some of the functions referenced in this section do not have
accompanying explanatory figures; you can obtain more information
on these functions and on the techniques discussed here from the
Presentation Manager technical references (see the Bibliography).
• 486 Programmer's Guide to the os/2 PresentationManager

Alternative Clipboard Formats


A data selection placed into the clipboard can use one of a variety
of formats. When you call WinsetclipbrdData to add a block of data to
the clipboard, you must pass this function a 16-bit value that identifies
the format. The application can define its own format, which is known
as a prz.zJ¢fe /or777#£. More commonly, however, it uses one of the pre-
defined standard formats, which can be recognized and used by a wide
variety of receiving applications. The following table lists the standard
clipboard formats:

Standard Identifier Data Format

CF TEXT Text format (described in the section


on Adding Data to the Clipboard)
CF BITMAP Bitmap format (described in Chapter 10)
CF METAFILE Metafile format
CF DSPTEXT Text display format associated with a
private format
CF DSPBITMAP Bitmap display format associated with
a private format

As you have seen, the CF_TEXT format is used to exchange standard


textual data. The CF BITMAP and CF METAFILE formats are used to
exchange graphical data. A block of graphical data stored in the
CF_BITMAP format is known as a Z7z.£777¢p, and consists of a sequence of
off and on bits that indicate the values of the actual screen pixels used to
create the image ®itmaps are discussed further in Chapter 10). A block
of graphical data stored in the CF_METAFILE format is known as a
777cf¢.Jc. Like a bitmap, a metafile stores a graphic image; however,
rather than storing each of the actual pixel values, a metafile stores the
sequence of Presentation Manager commands that are required to
recreate the image. Accordingly, a bitmap is displayed by copying the
bit values directly to video memory, while a metafile is displayed by
repJ¢yt.71g the sequence of commands that it stores.
Both bitmaps and metafiles can be stored in disk files or within
memory. When stored in memory, bitmaps and metafiles are identified
Interfacingwiththeclipboard 487 .

by handles. Once a program has a handle to a bitmap or metafile in


memory, it can display the image or perform other operations on the
data. When an application places a bitmap or metafile into the clip-
board, it must furnish the corresponding handle; when an application
obtains a bitmap or metafile from the clipboard, it receives the cor-
responding handle. Therefore, just as a block of textual data is ex-
changed through the clipboard by means of the far address of the
sharable segment containing the data, bitmaps and metafiles are ex-
changed by means of their handles.
Note that an application can insert a given set of data into the clip-
board in more than one format so that a wider variety of receiving ap-
plications can make use of the data. A receiving application can call the
Presentation Manager function WinEnumclipbrdFmts to obtain a list
of the formats currently contained in the clipboard; it can then request a
data block in the format that is most convenient.
When an application adds to the clipboard a block of data that has a
format defined by the application (a private format), it can insert an ¢d-
dz.£€.o71¢J block of data that conforms to a standard text or bitmap format.
An additional block in text format is identified by the value
CF_DSPTEXT, and an additional block in bitmap format is identified by
the value CF_DSPBITMAP. These additional blocks are used specifical-
ly by the cJz.pbo¢rd t7z.czucr zuz.71dozu, described in the next section. As you
will see, the clipboard viewer window displays the current clipboard
contents, and may be managed by another application (that is, 71of the
window viewer application), which may be unable to interpret the pri-
vate format. The clipboard viewer program will display a block of data
in the CF_DSPTEXT or CF_DSPBITMAP format in preference to a block
in a private format.

The Clipboard Viewer Window


An application can register a clipboard viewer window by calling
the Presentation Manager function Winsetclipbrdviewer. A clipboard
viewer window is responsible for displaying the current contents of the
clipboard, and it is sent the WM_DRAWCLIPBOARD message when-
ever the clipboard data change. Only one such window can be
registered at a given time.
• 488 Programmer's Guide to the os/2PresentationManager

Note that a clipboard viewer window may not be able to interpret


and display a privately formatted data selection placed in the clipboard
by another application. However, as mentioned in the previous section,
the other application may have provided an alternative data selection
conforming to a standard format that can be displayed by the viewer
window procedure. The viewer window should display these formats
(identified by CF_DSPTEXT and CF_DSPBITMAP) in preference to any
other formats in the clipboard.
Also, when an application calls WinsetclipbrdData to insert
privately formatted data into the clipboard, it may specify the flag
CFI_OWNERDISPLAY, which means that the calling application itself
is responsible for displaying this data within the clipboard viewer win-
dow (see Figure 9.3). (More precisely, this flag indicates that the current
clipboard ozu71cr window is responsible for displaying the data. The ap-
plication that inserts these data must therefore first call Winsetclipbrd-
Owner to establish its window as the current clipboard owner. The
owner window is subsequently sent a WM_PAINTCLIPBOARD mes-
sage whenever the clipboard viewer window needs repainting. Note
that the clipboard owner window and the clipboard viewer window are
typically separate windows; the clipboard owner is given the task of
repainting the clipboard viewer window only if the data selection has
been assigned the CFI_OWNERDISPLAY flag.)

Delayed Rendering of Clipboard Data


Preparing a block of data and inserting it into the clipboard (a
process known as rc7idcrl.7ig the data) may be a lengthy operation. There-
fore, the Presentation Manager allows a program to postpone rendering
the data until an application actually requests the specific format.
Delayed rendering is accomplished through the following steps:

• The program should call winsetclipbrdowner to register a clip-


board owner window.
• When the program calls winsetclipbrdData to insert the data
into the clipboard, it should specify the appropriate format
(through the third parameter), but pass a NULL data handle (as
the second parameter).
Interfacingwiththeclipboard 489 .

When an application calls WinQueryclipbrdData to request the


specified block, the system sends the owner window a
WM RENDERFORMAT message.
In response to this message, the owner window should render
the data. To render the data, the window procedure must
prepare the data and call WinsetclipbrdData again, this time
supplying the actual data handle for the given format.

Note that delayed rendering is especially useful for an application


that provides multiple alternative data formats. It need render only the
clipboard formats that are actually requested.
J pter ten

C:reating Icons,
Bitrnaps, and
Otfier Resources
491.

.r
hapter 7, which discussed menus and accelerator keys,
introduced the topic of Presentation Manager resources.
Chapter 8 then described dialog boxes, which are
another important resource. This chapter continues the
treatment of resources with a discussion of icons, pointers, bitmaps,
strings, and programmer-defined resource types.

• ICONSAND POINTERS
An icon is a fixed-size graphic image that you can design and dis-
play from your Presentation Manager application. The most common
use for an icon is to represent the program window when it has been
minimized. If you install a custom icon, the system will automatically
display this icon whenever the application window is minimized. (If
you do not install an icon, the system displays a small image of the cur-
rent program window, which may not clearly identify the application to
the user.) As you will see in this section, the application can also display
an icon within the client window or within a dialog box.
This section first describes how to design an icon using the Icon
Editor. It then explains how to install an icon so that it is displayed
when the application window is minimized, and how to explicitly dis-
play the icon within the client window or within a dialog box. Finally, it
introduces the closely related topic of mouse pointers, which are
described fully in Chapter 13.
The topics in this section are illustrated by the Presentation Manager
application presented in Figures 10.1 through 10.6. This program in-
stalls an icon that the system automatically displays when the window
is minimized. It also explicitly displays this same icon within the client
window, and provides an ``About" dialog box that displays the icon in
addition to a line of text and an OK push button. Figure 10.1 provides a
MAKE file for preparing this program; Figure 10.2 lists the linker defini-
tion file; Figure 10.3 contains the dialog box resource script generated
by the Dialog Box Editor; Figure 10.4 gives the general resource script;
Figure 10.5 provides the header file, which is included in the listings of
Figures 10.4 and 10.6; and Figure 10.6 lists the C source code.
• 492 Programmer'sGuidetothe os/2Presentation
Manager

Figure 10.1

This MAKE file prepares the program of Figures 10.1 through 10.6
FIG10 6.OBJ : FIG10 6.C FIG10 5.H
El /W2 /c /Zp 7G2ws FIG16 6.C

FIG10_6.EXE : FIG10_3.DLG FIG10 4.RC FIG10 5.H FIGIO 6.ICO


rc /r FIG10 4.RC

FIG10_6.EXE : FIG10 6.OBJ FIG10 2.DEF FIG10 4.RES


link /NOD FIG16_6.OBT,, NUI, OS2.LIB SIIBCE.LIB, FIGIO 2.DEF
rc FIG10 4.RES FIG10 6.EXE

• Figure 10.1..
A MAKE file for preparing the program of Figure 10 .6

Figure 10.2
; Linker definition file for the program listed in Figure 10.6®
NAME FIG10 6
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc
Aboutproc

• Figure 10.2..
Linker definition file for the program of Figure 10 .6

/*
Figure 10.3
Dialog resource script for the program of Figure 10.6
*/
DLGTEMPIIATE 256 LOADONCALL MOVEABLE DISCARDABLE
BEGIN
DIALOG MM, 256, 119, 31, 82, 84, Fs_NOByTEALIGN I Fs_DroBORDER
WS_VISIBLE I WS_CLIPSIBIINGS I WS_SAviBIfs

CONTROL ''Icon Demo", -1, 4, 67, 75, 10, WC_STATIC, SS_TEXT I


DT_CENTER I DT_TOP I WS_GROUP I WS_VISIBLE
CONTROL 1, -1, 33, 30, 16, 32, WC_STATIC, SS_ICON I WS_GROUP I
WS VISIBLE
CONTROL "OE", 1, 24, 7, 35, 12, WC_BUTTON, BS_PUSHBUTTON I BS_DEFAULT I
WS_TABSTOP I WS VISIBLE

• Figure 10.3..
Dialog box resource script for the program of Figure 10 .6
Creating Icons, Bitmaps, and Other Resources 493.

/*
Figure 10.4
General resource script for the program of Figure 10.6
*/
#include <OS2.H>
#include "FIG10 5.H"

POINTER ID FRAME RESOURCE FIG10 6.ICO

MENU ID FRAME RESOURCE


BEEIN
MENUITEM "About", ID ABOUT
END

rcinclude FIG10 3.DljG

a Figure 10.4..
General resource script for the program of Figure 10 .6

/*
Figure 10.5
Header file included in Figure 10.6 and Figure 10.4
*/
#def ine ID FRAME RESOURCE 1

#define ID ABOUT 10

#define ID ABOUTDLG 256

• Figure 10.5..
Header file included in the listings of Figures 10 .4 and 10 .6
•494 Programmer's Guide to the OS/2 Presentation Manager

/*
Figure 10.6

This program demonstrates the use of an icon.


*/

#def ine INCL WIN


#include <OSZ.H>
#include ''FIG10 5.H"

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

void main ()
(
HAB HAncBlk; /* Anchor block handle.
HMQ HMesQue; /* Message queue handle.
HWND HFrame, Hclient; /* Frame/client window handles.
QMSG QueMess; /* Message queue structure.
ULONG CtlData = /* Control windows to include:
FCF MENU /* Menu.
FCF-MINMAX /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
HAncBlk = Winlnitialize /* Initialize the PM. */
(0); /* Initialization options: must be 0. */
HMesQue = WincreateMsgQueue /* Create a message queue. */
(HAncBlk, /* Anchor block handle. */
0); /* Minimum queue size: 0 means default size.*/
WinRegisterclass /* Register window class for client window.
(HAncBlk, /* Anchor block handle.
''mlN„ ,
/* Window class name.
Wndproc , /* Window procedure associated with class.
CS SIZEREDRAW, /* Invalidate entire window on size change.
o)T /* Bytes of data storage for each window.
/*** Create standard window and load icon. ***********************************/
HFrame = Wincreatestdwindow /* Create a standard window collection.
(HWND DESKTOP, /* Parent window handle.
WS_VISIBLE I /* Frame window style: visible.
FS ICON, /* Load an icon.
&ctlData' /* Address of control data.
''RAIN„ ,
": Icon Demo", /* Client window class name.
/* Text for title bar.
OL, /* Client window style: none specified.
0, /* Resource module handle: EXE file.
ID FRAME RESOURCE, /* Resource identification.
&HElientT; /* Address to receive client window hand.

• Figure 10.6..
An application illustrating the use of icons
Creatinglcons,Bitmaps,andotherResources 495 .

while (WinGetMsg /* Get messages until WM_QUIT.


(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure.
0, /* Window filter: any window.
0, /* First message identifier: n/a.
0)) /* Last message identifier: n/a.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

WinDestroywindow (HFrame) ; /* Eliminate the window.


WinDestroyMsgQueue (HMesQue) ; /* Eliminate the message queue.
WinTerminate (HAncBlk) ; /* Sever ties with the Presentation
/* Manager and release resources.
} /* end main */

HPOINTER Hlcon; /* Icon handle.


MRESULT EXPENTRY Wndproc
(HWND hwnd, /* Window handle.
USHORT msg, /* The message.
MPAEun mpl, /* Message-specific information.
MPARAM mp2) /* Message-specific information.
(
switch (msg)

5ase wM CREATE: /* Sent when window is first created.


return Create (hwnd, msg, mpl, mp2);

case WM DESTROY: /* Sent when window is destroyed.

return Destroy (hwnd, msg, mpl, mp2) ;


case WM COMMAND: /* Process messages from menu.

return Command (hwnd, msg, mpl, mp2) ;

case WM PAINT: /* Process window paint message.


return Paint (hwnd, msg, mpl, mp2) ;
default: /* Perform the default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;
)

} /* end Wndproc */

• Figure 10.6..
An application illustrating the use of icons (continued)
• 496 Programmer'sGuidetothe os/2Presentation
Manager

MRESULT EXPENTRY Aboutproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
switch (msg)
(
case WM COMMAND:

switch (COMMANDMSG(&msg) ->cmd)


(
case DID OK:
case DID-CANCEL:
Win5ismissDlg (hwnd,TRUE) ;
return FALSE;
default:
return FALSE;
)

return WinDefDlgproc (hwnd, msg, mpl, mp2) ;

} /* end Aboutproc */

MRESULT EXPENTRY Command (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
USHORT Result;

switch (COMMANDMSG (&msg) ->cmd)


(
case ID ABOUT: /* 'About' item 'File' submenu.
Result = WinDlgBox /* Display 'About' dialog box.
(HWND DESKTOP, /* Handle of parent window: desktop.
hwnd , /* Handle of owner: client.
Aboutproc , /* Dialog procedure.
NULL' /* Resource module: the .EXE file.
ID ABOUTDLG, /* Name ID of dialog window: About.
NUE:L) ; /* Pointer to procedure data: n/a.
return FALSE;
default:
return FALSE;
)

} /* end Command */

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** Load the icon. ************************************************"********/

Hlcon = WinLoadpointer
(HWND DESKTOP, /* Handle of desktop window.

• Figure 10.6..
An application illustrating the use of icons (continued)
Creatinglcons,Bitmaps,andotherResources 497 .

NULL, /* Module handle: EXE file.


ID FRAME RESOURCE) ; /* Resource identifier.
ret.urn FALSE;

} /* end Create */

mESULT EXPENTRY Destroy (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** Remove the icon resource from memory. ***********************************/
WiriDestroypointer
(Hlcon) , /* Icon handle.
ret.urn FALSE ;

} /* end Destroy */

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
*/
::i;TF.pE:::Pace ; ,: ::::::t:::::n::::e±:a:€::;w coordinates. */
static char Message [] = /* Text to display. */
"This window displays an icon.";

HPI.esspace = WinBeginpaint /* Returns presentation space handle. */


*/
(hwnd /* Window handle. */
0' /* 0 requests a cache presentation space.
0); /* Addre-ss of variable to set to invalid region: none.*/
WiriQuerywindowRect /* Obtain coordinates of client window.
&R:::; ; ,: ¥::::¥u::n::e;ece±ve coordinates.
WinDrawText /* Draws a single line of formatted text into a rectangle.
( Hpresspace , * Presentation space handle
Oxffff, * Length of string: Oxffff means 0 terminated.
Message , * Text to be displayed.
&Rect, * Coordinates of rectangle containing text.
CLR BIACK, * Foreground color.
cm-WHITE, * Background color.
* Drawing specifications:
* Center text horizontally.
3:-S::E::R I * Center text vertically.
DT-ERASERECT) * Erase the rectangle (entire window) .

/*** Draw t:he ±con. **********************************************************/

WinDrawpointer
5Tpresspace , /: ::::::::::o:o:::::a::?dle. :/
0, /* Vertical coordinate. */
Hlcon, /* Icon handle. */

• Figure 10.6..
An application illustrating the use of icons (continued)
• 498 Programmer'sGuidetothe os/2Presentation
Manager

DP NORMAL) ; /* Flag: normal pointer appearance. */


WinEndpaint (Hpresspace) ; /* Tells Presentation Manager that */
return FALSE; /* redrawing is complete. */

) /* end Paint */

• Figure 10.6..
An application illustrating the use of icons (continued)

Designing an Icon
The first step is to design the icon using the Icon Editor,
ICONEDIT.EXE. The Icon Editor is a Presentation Manager application
that provides a rectangular drawing area having the proportions of a
standard icon. You can use the mouse to draw the desired icon within
this area, pixel-by-pixel. You can assign each of these pixels one of the
following four colors:

Color Visual Effect

Black Pixel displayed as black


White Pixel displayed as white
Screen Screen color underlying pixel is displayed
Inverse-screen Screen color underlying pixel is inverted

The left mouse button toggles between the black and white colors, and
the right mouse button toggles between the screen and inverse-screen
colors. Pixels that are assigned the screen color show the underly-
ing color of the screen and are thus invisible. Pixels assigned the in-
verse-screen color always contrast with the underlying color; for
example, if the current underlying color is yellow, the icon pixel will be-
come the inverse color, blue.
Figure 10.7 illustrates the Icon Editor containing the icon that is dis-
played by the application of Figure 10.6. The rectangular area on the
right is the editing window used to draw the icon, which is displayed
much larger than its actual size. The rectangular area on the left is the
Creating Icons, Bitmaps, and Other Resources 499.

viewing window, which displays a true scale replica of the icon. The
icondepictedinFigure10.7hasawhitebackgroundwithablackborder
and black letters; it is thus visible over any background screen color.
Note that assigning certain color combinations may render the icon in-
visible when it is displayed on top of some backgrounds; for example,
an icon that is given a screen-colored background and a black
foreground will disappear when displayed within a black screen area.
Before you create a new icon with the Icon Editor (through the New
item of the File submenu), you must specify the number of pixels that
the icon is to contain. You can choose one of the following values:

Resolution Pixels Display Adapter Type


(width x height)

Low 32x 16 CGA

Medium 32 x 32 Standard EGA or VGA

High 64 x 64 Higher-resolution systems

The editing window allows you to manipulate the designated num-


ber of pixels, and the value of each of these pixels is recorded in the file
that stores the icon image. However, because an icon displayed on the

• Figure 10.7..
The Icon Editor with an example icon
• 500 Programmer's Guide to the os/2Presentation
Manager

screen always has approximately the same size, the actual number of
pixels used to draw the icon depends upon the current screen resolu-
tion. For example, if you create an icon with 32 % 16 pixels (the number
of pixels used to draw the icon with a CGA adapter), and then display
the icon with an EGA system, the Presentation Manager must duplicate
every other row of pixels. Likewise, if you designate an icon with 64 %
64 pixels and then display this icon on a EGA system, the Presentation
Manager must eliminate every other row and column. Because adding
or removing pixels degrades the original image designed in the Icon
Editor, it is best to designate the same number of pixels that will ul-
timately be used to display the icon. However, if the program must run
on a variety of target machines, the best choice might be the medium
resolution, 32 % 32 pixels.
When you have completed designing the icon, you should save the
data in a file through the File submenu. If you do not specify a file ex-
tension, it is automatically given the .ICO extension. For further infor-
mation, see the documentation and online help information provided
with the Icon Editor.

Installing an Icon
This section describes how to associate an icon with the standard
window so that the system automatically displays this icon when the
application window is minimized.
First, because the data for an icon is stored as a Presentation Manager
resource, you must write a script to direct the resource compiler to in-
clude these data in a resource segment in the executable file. An icon is
defined within the resource script with the keyword POINTER, fol-
lowed by an identifier and the name of the file generated by the Icon
Editor. The example resource script in Figure 10.4 assumes that the icon
created with the Icon Editor was saved in the file FIG10 6.ICO, and it
defines the icon using the following line:
POINTER ID FRARE RESOURCE FIG10 6.ICO

Note that if you are going to associate an icon with the standard win-
dow, and if the application also uses a menu or accelerator table, you
must assign the icon the scz777c identifier used for the menu and
Creating Icons, Bitmaps, and OtherResources 501 .

accelerator table. When the resource compiler encounters the icon


definition, it obtains the icon data from the specified file and inserts
these data directly into the binary resource file (.RES), which will sub-
sequently serve as the source of the data inserted into the program file.
See the MAKE file of Figure 10.1 for the commands used to prepare the
programresources,andseeChapter7forageneraldiscussiononusing
the resource compiler.
Ificondataarecontainedwithinaresourcesegmentintheexecutablepro-
gram, you can associate the icon with the standard window sinply by in-
cluding the appropriate parameters in the can to Wincreatestdwindow
(Figure2.5).TheprogramofFigure10.6callsthisfunctionasfo11ows:

HFrame = Wincreatestdwinow
(Hum DESKTOp. /* Parent window handle.
WS VI;IBLE I /* Frame window style: visible.
FS ICON /* Load an icon.
&CtlData, /* Address of control data.
\\RAIN,, , /* Client window class name.
"Icon Demo'', /* Text for title bar.
OL, /* Client window style:
/* none specified.
0, /* Resource module handle:
/* .EXE file.
ID FRARE RESOURCE /* Resource identifier.
&Hclient) ,. /* Address to receive
/* client window hand.

The following three parameters passed to Wincreatestdwindow


cause the system to associate the icon with the standard window:

• The frame style parameter (the second parameter, flstyle) in-


cludes the constant FS ICON, which indicates that an icon is to
be loaded and displayed when the window is minimized.
The module handle parameter (the seventh parameter, hmod) is
given a value of 0, indicating that the resource segment contain-
ing the icon data is located within the executable file. (Altema-
tively, if the icon data were contained in a dynamic-link library
file, you would have to first call DosLoadModule to explicitly
load these data, and then pass the module handle returned by
• 502 Programmer'sGuidetothe os/2Presentation
Manager

DosLoadModule as the hmod parameter to Wincreatestd-


Window.)
The resource identifier parameter (idResources, the eighth
parameter) is given the value ID_FRAME_RESOURCE, which is
the identifier assigned to the icon in the resource script.

Once a custom icon has been associated with the standard window
through the call to Wincreatestdwindow, the system automatically
displays this icon whenever the user minimizes the window; no further
program action is required to manage the icon.

Displaying an Icon
within the Client Window
If you have designed an icon and included the icon data in a pro-
gram resource segment as described in the previous section, you can
also display the icon at any position within the client window. To ex-
plicitly display the icon in the client window, you should perform the
following three steps from the client window procedure:

• Call the winLoadpointer presentation Manager function (Figure


10.8) to load the icon data from the resource segment into
memory.
• Call winDrawpointer (Figure 10.9) to display the icon ata
specified position within the window. To call this function, you
must have a valid handle to a presentation space.
• When you have completed displaying the icon, call the win-
Destroypointer function (Figure 10.10) to release the memory
containing the icon data.

Note that rather than creating a custom icon, and obtaining a handle
to this icon by calling WinLoadpointer, you can obtain the handle to a
pointer provided by the system by calling the WinQuerysyspointer
function (Figure 11.7). System icons can be displayed within the client
window by calling WinDrawpointer. Chapter 11 explains the Win-
Querysyspointer function and illustrates the system icons.
Creating Icons, Bitmaps, and OtherResources 503 .

WinLoadpointer
Purpose..
Loads an icon or mouse pointer into memory from a
resource segment contained in a disk file.

Prototype..
HPOINTER APIENTRY WinLoadpointer
(HWND hwndDesktop, Eh;gtBiesrKoi6hp: desktop window/

ENODULE hood ' Feesso°uurrccee£Fc°odnii:nheadnSLiet'rifnti#e

exeoutable file, this parameter must be


assigned NULL; if the resource is in a
dynamic-hnk module, the parameter
must contain the module handle
returned by DosLoadModule.
USHORT idres) ,. The identifier assigned to the icon or
pointer in the resource script.

RetumValue..
The handle of the newly loaded icon or pointer, or the value
NULL if an error occurred.

Notes..
When the resource loaded by this function is no longer re-
quired, it should be released by calling WinDestroypointer.

Related Functions ..
WinDestroypointer (Figure 10.10)

• Figure 10.8..
The W±r\LoaLdpointer Presentation Manager function
• 504 Programmer'sGuidetothe os/2Presentation
Manager

WinDrawpointer
Purpose..
Draws an icon.

Prototype..
BOOL APIENTRY WinDrawpointer
(Hps hps , Handle of the presentation space in which
the icon is to be drawn.
SHORT x, x-coordinate of position where lower left
corner of icon should be placed.
SHORT y, y-coordinate of position where lower left
corner of icon should be placed.
HPolNTER hptr, Handle oftheiconretumed by
WinLoadpointer.
USHORT fs) ,. Flags specifying how the icon is to be drawn;
you can choose from the following values:

Value Effect
DP NORMAL Draw the icon
without modification
DP HALFTONED Drawtheblackareas
of the icon with a
halftoned pattern
DP INVERTED Invert the icon colors;
that is, substitute
black for white and
white for black

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Related Functions ..
WinLoadpointer (Figure 10.8)

• Figure 10.9..
The W±nDra:wPo±uler Presentation Manager function
Creating Icons, Bitmaps, and Other Resources 505.

WinDestroypointer
Purpose..
Destroys an icon or pointer.

Prototype..
BOOL APIENTRY WinDestroypointer
(HpolNTER hptr) ,. Pointer handle returned by
WinLoadpointer.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Related Functions ..
WinLoadpointer (Figure 10.8)

• Figure 10.10..
Tire WLnDestraypointer Presentation Manager function

The window procedure in the example program of Figure 10.6 calls


WinDrawpointer to display the icon within the client window each
time it receives the WM_PAINT message (Figure 2.19). So that the icon
handle will be available throughout the lifetime of the window, the pro-
gramcallsWinLoadpointerduringtheprocessingoftheWM_CREATE
message(Figure3.16;rememberthatthismessageissentwhenthewin-
dow is first created, before the initial WM_PAINT message). The
WM_CREATE message is handled by the function Create, which calls
WinLoadpointer as follows:

HPOINTER Hlcon,.

Hlcon = WinLoadpointer
(HWND DESKTOP, /* Handle of desktop window. */
• 506 Programmer'sGuide tothe os/2Presentation
Manager

NULL, /* Module handle: .EXE file. */


ID FRARE RESOURCE) ,. /* Resource identifier. */

Note that Hlcon is declared as an external variable; therefore, the icon


handle that it receives from WinLoadpointer will be available for sub-
sequent use by the WM_PAINT routine.
Before the window is destroyed, the client window procedure calls
WinDestroypointer to free the memory occupied by the icon data. The
client window is notified of its impending destruction through the
WM_DESTROY message (Figure 10.11). The function that processes this
final message, Destroy, calls WinDestroypointer as follows:

WinDestroypointer
(Hlcon) ,. /* Icon handle. */

WM DESTROY
Purpose..
This message is sent by the system to a window when it is
about to be destroyed.

Parameters..
I@ARAM mpl NULL.
MPARAM mp2 NULL.

Return Value ..
NULL.

Notes..
This message is sent to the window procedure after the win-
dow has been hidden on the screen, and it allows the ap-
plication to perform any final tasks required before the
window is destroyed.

• Figure 10.11..
The WM_DESTROY Presentation Manager message
Creatinglcons,Bitmaps, and otherResources 507 .

TheprogramofFigure10.6processestheWM_PAINTmessageinthe
function Paint. This function performs the following series of steps:

1. It calls winBeginpaint to obtain a handle to a presentation space.


2. It calls winQuerywindowRect to obtain the current coordinates
of the client window in a RECTL structure.
3. In calls winDrawText to display a single line of text in the center
of the window.
4. It calls winDrawpointer to display the icon at the lower left
corner of the window.
5. It calls winEndpaint to release the handle to the presentation
space and to notify the system that the window has been
updated.

The call to WinDrawpointer is as follows:

WinDrawpointer
(Hpresspace, /* Presentation space handle.
0, /* Horizontal coordinate.
0, /* Vertical coordinate.
Hlcon, /* Icon handle.
DP NORMAI.) ,. /* Flag: normal pointer appearance.

Note that the second and third parameters supply the location within
the client window where the system places the lower left corner of the
icon; this call therefore causes the icon to appear in the lower left comer
of the window, touching the left and bottom window edges. You do not
need to specify the dimensions of the icon, since it is drawn with a fixed
size (the icon is always given the same size, whether it is used to repre-
sent a minimized window, or is drawn within the client window or
within a dialog box). Alternatively, bitmaps, which are discussed later
in the chapter, can be drawn to fill any given rectangular dimensions.
You may have noticed that the call to WinRegisterclass in the ex-
ample program of Figure 10.6 specifies the CS_SIZEREDRAW style
(explained in Table 2.1). This style forces the system to invalidate the en-
tire client window (and thus send a WM_PAINT message) whenever
the user changes the window size. Previous examples in the book did
• 508 Programmer's Guide to the os/2 PresentationManager

not require this style, because all data displayed by these programs
were aligned with respect to the upper left corner of the client window,
and the system ¢#fo77z¢£!.c¢JJy realigns data with respect to this corner
whenever the window size is changed. (If the CS_SIZEREDRAW style
is 7tof specified, the system does not invalidate the window or send a
WM_PAINT message when the window size is reduced; when the win-
dow is enlarged, the system sends a WM_PAINT message but in-
validates only the newly exposed area.) The current example program,
however, justifies the text string in the cc7ifcr of the window, and aligns
the icon with the Jozucr left corner of the window. Thus, the
CS_SIZEREDRAW style is mandated (you might try recompiling the
program without this style to observe the difference).
A 7iofc ¢Z7o#f cr¢s3.7ig #7c cJz.c7if zu3.7zdoztr Unlike the WM_PAIP\IT routines
presented previously in the book, the current version of Paint does not can
WinFillRect to explicitly erase the client window. Rather, when this func-
tion cans WinDrawText (Figure 2.24), it includes the value DT_ERASE-
RECT within the flag parameter (the last parameter), as fouows:

WinDrawText
(Hpresspace, /* Presentation space handle.
Oxffff, /* Length of string:
/* Oxffff means 0-terminated.
Message, /* Text to be displayed.
&Rect, /* Coordinates of rectangle
/* to contain text.
CLR BI.ACK, /* Foreground color.
CLR WHITE, /* Background color.
/* Drawing specifications :
DT CENTER I /* Center text horizontally.
DT VCENTER I /* Center text vertically.
DT-ERASERECT) /* Erase the rectangle
/* (entire window) .

The DT_ERASERECT flag causes this function to erase the rectangular


area given by the fourth parameter (a pointer to a RECTL structure) by
filling this area with the background color specified through the sixth
parameter. Because the RECTL structure Rect contains the current coor-
dinates of the client window, the call to WinDrawText effectively erases
Creating Icons, Bitmaps, and Other Resources 509.

the entire window before displaying the string. (The program therefore
calls WinDrawText before calling WinDrawpointer!)
Note that when erasing the client window by calling WinFillRect, or
WinDrawText with the DT_ERASEFLAG, you can specify an explicit
color value to be used to fill the window, which thereby becomes the
window background color. You can alternatively specify the value
CLR BACKGROUND, which refers to the current default background
color~that has been set by the user through the Control Panel utility
described in Chapter 1. If you specify the default background color by
passing CLR_BACKGROUND when erasing the client window, you
should also specify the default foreground color, CLR_NEUTRAL,
when displaying characters through WinDrawText or Gpicharstring-
At (otherwise, you could end up with an undiscernible color combina-
tion such as white characters on a white background). The possible
color values are listed in Figure 2.23.
An alternative method for erasing the client window with the default
backgroundcoloristocallthePresentationManagerfunctionGpiErase
(Figure 10.12), which erases the entire window associated with the

GpiErase
Purpose..
Erases the specified presentation space by filling the area
with the default system background color (CLR_BACK-
GROUND).

Prototype..
BOOL APIENTRY GpiErase
(Hps hps) ,. Handle of the presentation space.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

• Figure 10.12..
The GPIEraLse Presentation Manager function
• 510 Programmer'sGuidetothe os/2Presentation
Manager

specified presentation space. You do not specify a background color


when cauing GpiErase; it automatically uses the default background
color.
Note that all the example programs in this book specify explicit color
values-a black foreground against a white background-for the sake
of simplicity and because of some inconsistencies in the manner colors
were managed in the early versions of the Presentation Manager.

Displaying an Icon within a Dialog Box


If you have created an icon and included the icon data as a
resource in the executable file, you can also display this icon within
a dialog box. When you are designing a dialog box in the Dialog Box
Editor,youcanaddanicontothecollectionofdialogcontrolsbyselect-
ing the Icon control item from the Control submenu. You will notice
that you can move the icon within the dialog box, but you cannot
change its size, since an icon is a fixed-size graphic image. Note also
that when assigning the icon styles, the Text field does 71of contain a text
string:b+tr_at~h.=r._in_u_st.be..a5sjgnedtheidentifieroftheiconresourcethatap-

p±rs^int`he`Pply.TERde.finition|ntheresourcefile.Your\eedtoassigr\tLe
ID Symbol field a unique value only if you are going to reference
the icon within the C program.
The example application of Figure 10.6 displays an About dialog box
when the user selects the About menu item (which is the only item in
the program menu). This dialog box is illustrated in Figure 10.13; note
that it displays the program icon in addition to a text string and a push
button. Figure 10.14 illustrates the manner in which the icon styles were
defined in the Dialog Box Editor; the Static Styles box appears when the
icon control is first positioned and whenever you choose the Styles item
of the Edit submenu when the icon is selected. Note that the Text field is
assigned the value 1 (ID_FRAME_RESOURCE), which is the identifier
given to the icon in the POINTER statement within the resource file
(Figure 10.4). The ID Symbol field is assigned -1, since the icon does not
need to be referenced within the C source code.
The program menu is created and managed as described in Chapter
7, and the About dialog box is displayed and dismissed in the same
Creating Icons, Bitmaps, and OtherResources 511 .

manner as the About dialog box presented in Chapter 8. The system


automatically loads and displays the icon, along with the other dialog
controls, when the dialog box is activated through the WinDlgBox
function.

• Figure 10.13..
The About dialog box

• Figure 10.14..
Defining the icon in the Dialog Box Editor
• 512 Programmer's Guideto the os/2Presentation
Manager

Designing a Mouse Pointer


The structure of the graphic data used to draw a mouse pointer is
the same as that used for an icon. Accordingly, you can create and load
a custom mouse pointer in a manner similar to the method employed
for an icon. Specifically, you should perform the following steps:

• Design the custom pointer in the Icon Editor, selecting the


desired resolution. Note that you can select the ``screen'' color for
areas outside of a nonrectangular pointer image. Also, when
designing a pointer in the Icon Editor, you should designate a
hot-spot pixel through the Edit submenu; the concept of the
pointer hot spot is explained in Chapter 11. The resulting file will
be saved with the .PTR extension.
• Define the pointer in the resource file using the POINTER
keyword in the same manner as an icon; note, however, that the
identifier should be dz.s£2'71cf from that used for the icon or any
other pointers you define for the application.
• Load the pointer data using winLoadpointer and release these
data using WinDestroypointer, in the same manner as an icon.
• Rather than displaying a pointer with winDrawpointer (used to
draw an icon), however, you should call Winsetpointer
(described in Chapter 11) to force the Presentation Manager to
use your custom mouse pointer in place of the default system
pointer.

Chapter 11 provides an example program that displays a custom


mouse pointer, and also shows how to use the alternative pointers
provided by the system, such as the hourglass pointer normally dis-
played during a lengthy operation.

® BITMAPS
As stated in Chapter 9, a bitmap is a data structure that stores a
graphic image; it consists of a sequence of off and on bits that indicate
the values of the actual screen pixels used to create the image. Bitmaps
Creatinglcons,Bitmaps,andotherResources 513 .

can be stored in a disk file or in memory. A bitmap is a more versatile


medium than an icon or a pointer (icons and pointers are actually spe-
cialized forms of bitmaps). A bitmap can store the values of a variable
number of pixels; it can hold either a monochrome or a color image; and
the size of a bitmap can be readily adjusted when it is loaded into
memory or displayed on a device.
This section discusses how to create a monochrome bitmap using the
Icon Editor, how to store the bitmap as a Presentation Manager
resource, and how to display the graphic image stored in the bitmap
within the client window. The procedures described in this section thus
use bitmaps as so%rces of fixed graphics data. Note that an application
can also create or modify bitmaps at run-time; thus, bitmaps can be
used to 7`cccz.I;c graphics data in a manner similar to an output device
such as a screen or plotter. (To send graphics data to a bitmap at run-
time, you can associate a presentation space with the bitmap, and then
perform normal graphics operations on this presentation space. This
topic, however, is beyond the scope of the book, which discusses only
presentation spaces that are associated with windows.)
The techniques discussed in this section are illustrated by the ex-
ample application given in Figures 10.15 through 10.19, which loads
and displays a bitmap so that the graphic image completely fills the
client window.
To create a bitmap with the Icon Editor, select the New item of the
File submenu and choose the Bitmap selection when the dialog box ap-
pears. You must then specify the total number of horizontal and vertical
pixels you want to work with when you design the bitmap. You can
choose any number of horizontal and vertical pixels in the range from 1
to 99 (in contrast to icons and pointers, for which you can select one of
only three fixed resolutions). Note that the choice of the number of
pixels will affect the resolution of the final image displayed in the win-
dow, but it will 71of affect the size of the image; as you will see, the over-
all size and proportions can be adjusted either when you load or when
you draw the bitmap.
Designing a bitmap using the Icon Editor is the same as designing an
icon or pointer, except that you can select only black and white color
values (as opposed to the four color values used for icons and pointers),
since the Icon Editor can create only monochrome bitmaps. The bitmap
• 514 Programmer's Guide to the os/2PresentationManager

# Figure 10.15
#
# This MAKE file prepares the program of Figures 10.15 through 10.19
#
FIGlo l9.OBT : FIG1019.C FIG1018.H
El /W2 /c /Zp /E2ws FIG101i.C

FIG1019.EXE : FIG1017.RC FIGlo 18.H FIG1019.BMP


=c /r FIGlo 17.EC

FIG10_19.EXE : FIGIO 19.OBT FIGIO 16.DEF FIG1017.RES


link /NOD FIG10=19.OBT,, NULT OS2.LIB SLIECE.LIB, FIG1016.DEF
rc FIG1017.RES FIG1019.EXE

• Figure 10.15..
A MAKE file for preparing the program of Figure 10 .19

Figure 10 .16
; Linker, definition file for the program listed in Figure 10.19
NAME FIG10 19
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 10.16..
Linker definition file for the program of Figure 10 .19

/*
Figure 10.17

General resource script for the program of Figure 10.19


*/
#include <OS2.H>
#include "FIG1018.H"

STRINGTABLE
BEGIN
ID PROGNAME, '': Bitmap Demo"
EN5

BITMAP ID BITMAP FIG1019.BMP

• Figure 10.17..
General resource script for the program of Figure 10 .19
Creatinglcons,Bitmaps, and otherResources 515 .

/*
Figure 10.18

He€ider file to be included in Figure 10.17 and Figure 10.19


*/

#def ine ID PROGNAME 0


#def ine ID-BITMAP 1

• Figure l0®18..
Header file in.cluded in the listings of Figures 10 .17 and 10 .19

/*
Figure
*/

#def ine INCL WIN


#include <OSZ.H>
#include ''FIG1018.H"

MRESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

void main ()
(
HAB RAncBlk; /* Anchor block handle.
HMQ HMesQue; /* Message queue handle.
HWND HFrame, Hclient; /* Frame/client window handles.
QMSG QueMess; /* Message queue structure.
char ProgName [32] ; /* Holds program name string.
ULONG CtlData = /* Control windows to include:
FCF MINMAX /* Minimize/maximize box.
FCF-SHELLPOSITI0N /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
HAncBlk = Winlnitialize /* Initialize the PM. */
(0); /* Initialization options: must be 0. */
HMesQue = WincreateMsgQueue /* Create a message queue. */
(HAncBlk, /* Anchor block handle. */
0); /* Minimum queue size: 0 means default size.*/
WinRegisterclass /* Register window class for client window.
(HAncBlk, /* Anchor block handle.
''MAIN„ ,
/* Window class name.
Wndproc , /* Window procedure associated with class.
CS SIZEREDRAW, /* Invalidate entire window on size change.
o)T /* Bytes of data storage for each window.

• Figure 10.19:
An application that loads and displays a bitmap
• 516 Programmer's Guide to the os/2PresentationManager

WinLoadstring
(HAncBlk, /* Anchor block handle.
NULL, /* Module handle: in EXE file.
ID PROGNAME, /* String identifier.
sizeof (ProgName) /* Size of rec.eiving buffer.
ProgName) ; /* Receiving buffer.
HFrame = Wincreatestdwindow /* Create a standard window collection.
(HWND DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style: visible.
&cEIData, /* Address of control data.
''RAIN„ ,
/* Client window class name.
ProgName , /* Text for title bar.
OL, /* Client window style: none specified.
0, /* Resource module handle: n/a.
0, /* Resource identification: none.
&Hclient) ; /* Address to receive client window hand.
while (WinGetMsg /* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure.
0' /* Window filter: any window.
0, /* First message identifier: n/a.
0)) /* Last message identifier: n/a.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

WinDestroywindow (HFrame) ; /* Eliminate the window.


WinDestroyMsgQueue (HMesQue) ; /* Eliminate the message queue.
WinTerminate (HAncBlk) ; /* Sever ties with the Presentation
/* Manager and release resources.
} /* end main */

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
MRESULT EXPENTRY Destroy (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

HBITMAP HBitmap; /* Bitmap handle. */


MRESULT EXPENTRY Wndproc
(HWND hwnd, /* Window handle. */
USHORT msg, /* The message. */
MPARAM mpl, /* Message-specific information. */
MPAEN mp2) /* Message-specific information. */
(
switch (msg)
(
case WM CREATE: /* Sent when window is first created.
return Create (hwnd, msg, mpl, mp2);
case WM DESTROY: /* Sent when window is destroyed.

return Destroy (hwnd, msg, mpl, mp2) ;

• Figure 10.19..
An application that loads and displays a bitmap (continued)
Creatinglcons,Bitmaps,andotherResources 517 .

case WM PAINT: /* Process window paint message.

return Paint (hwnd, msg, mpl, mp2) ;


default: /* Perform the default processing on all other messages. */
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;
)

} /* end Wndproc */

M:RESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS IJpresspace;

/*** Obt.ajLn a handle to a window presentation space. *************************/


HPI.esspace = WinGetps (hwnd) ;

/*** Lo€id the bitmap. ********************************************************/

HBitmap = GpiLoadBitmap
( Hpresspace , /* Handle to presentation space.
NULL' /* Resource module handle: EXE file.
ID BITmp, /* Identifier of bitmap resource.
OL, /* Width to stretch bitmap: no stretch
OL); /* Height to stretch bitmap: no stretch
/*** Release the presentation space. *****************************************/
WinReleaseps (Hpresspace) ;

ret,ui-n FALSE ;

} /* end Create */

MRESULT EXPENTRY Destroy (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/*** Remove the bitmap resource from memory. *********************************/
GpiDeleteBitmap
(HBitmap) ; /* Bitmap handle.
ret.urn FALSE;

} /* end Destroy */

MRESULT EXPENTRY Paint (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

E:Ej:T:P::::pace ; ,: ::::::t:::::n:i::e±:a:€::;w coordinates.


Hpresspace = WinBeginpaint /* Returns presentation space handle.
(hwnd, /* Window handle.

• Figure 10.19:
An applica.IL.ion that loads and displays a bitmap (continued)
• 518 Programmer's Guide to the os/2PresentationManager

8; , /: 2d:::::s:: :a:::::ep::s:::a::o:n:::::. re.ion: none. :/


WinQuerywindowRect /* Obtain coordinates of client window.
(hwnd, /* Window handle.
&Rect) ; /* Structure to receive coordinates.
/*** Draw the bitmap. ********************************************************/

WinDrawBitmap
( Hpresspace , /* Presentation space handle. */
HBitmap , /* Bitmap handle from GpiLoadBitmap. */
NULL, /* Section of bitmap to draw: NULL = ALL.*/
( PPOINTL) &Rect , /* Pointer to rectangle to fill. */
CLR NEUTRAL, /* Foreground color: system default. */
CLR-BACKGROUND, /* Background color: system default. */
DBM-STRETCH) ; /* Flag: fill rectangle with bitmap. */
WinEndpaint (Hpresspace) ; /* Tells Presentation Manager that */
/* redrawing is complete. */
return FALSE;

) /* end Paint */

• Figure 10.19..
An application that loads and displays a bitmap (continued)

displayed by the example application of Figure 10.19 uses 50 x 50 pixels,


and it is shown within the Icon Editor in Figure 10.20.
When you save a bitmap file, the system will assign it the .BMP ex-
tension. The next step is to define the bitmap in the resource script. Bit-
maps are defined following the BITMAP keyword; the example
resource script in Figure 10.17 defines a bitmap using the following line:

BITMAP ID BITMAP FIG1019.BIB

This example assumes that the bitmap designed in the Icon Editor was
saved under the name FIG10 19.BMP. Note that the identifier ID BIT-
MAP, which is defined in the header file of Figure 10.18, win be us-ed to
refer to the bitmap within the C source code of Figure 10.19.
Creatinglcons,Bitmaps,and otherResources 519 .

• Figure 10.20..
The example bitmap within the Icon Editor

Once the bitmap data have been placed in a resource segment within
the executable file, you can display the bitmap within the client win-
dow by performing the following function calls:

• Call GpiLoadBitmap (Figure 10.21) to load the bitmap from the


resource segment into memory. When you call this function, you
must have a valid handle to a presentation space.
Call WinDrawBitmap (Figure 10.22) to display the bitmap
within the client window. You must also have a valid handle to a
presentation space when calling this function.
When you have completed displaying the bitmap, call Gpi-
DeleteBitmap (Figure 10.23) to release the bitmap from memory.

The overau structure of the bitmap demonstration program of Figure


10.19 is quite sinular to that of the icon demonstration program of Figure
10.6.Inbothprograms,theresourceisloadedinresponsetotheWM_CRE-
AIE message, it is displayed during processing of the WM_PAINT mes-
sage, and it is released upon receipt of the WM_DESTROY message. The
• 520 Programmer's Guide to the os/2 PresentationManager

WM_CREATE message is processed by the function Create, which


loads the bitmap using the following instructions:

HPS Hpresspace,.

Hpresspace = WinGetps (hwnd) ,.

HBitmap = GpiLoadBitmap
(Hpresspace, /* Handle to presentation space. */
NULL, /* Resource module handle: .EXE file.*/
ID BITMAP, /* Identifier of bitmap resource. */
OL, /* Width to stretch bitmap: */
/* rro fg+rcatc:A. *I
OL) ,. /* Height to stretch bitmap: */
/* rro Es+rcitc:A. */

WinReleaseps (Hpresspace) ,.

Note that unlike the function WinLoadpointer, which loads an icon or


pointer, the function GpiLoadBitmap requires a handle to a presenta-
tion space. If possible, the system will store the bitmap data within
memory provided by the device associated with this presentation space
(which, in this case, is the video display device). Note that the identifier,
ID_BITMAP, passed as the third parameter, is the same value assigned
to the bitmap by the BITMAP definition in the resource script. The
fourth and fifth parameters to this function allow you to adjust the size
of the bitmap as it is loaded; specifically, the fourth parameter gives the
number of horizontal pixels and the fifth parameter the number of ver-
tical pixels. If either of these two parameters contains a nonzero value,
the system will adjust the bitmap as it is copied into memory to contain
the requested number of horizontal or vertical pixels; if either of these
values is zero, the system will preserve the original number of pixels in
the corresponding direction. The example application assigns a value of
0 to both parameters; therefore, the bitmap retains the number of pixels
assigned when it was created in the Icon Editor (which was 50 x 50).
Note, however, that the size of the bitmap will be adjusted when it is
actually displayed in the client window.
Creatinglcons,Bitmaps, and otherResources 521 .

GpiLoadBitmap
Purpose..
Loads a bitmap from a resource segment into memory.

Prototype..
HBITMAP APIENTRY GpiLoadBitmap
(Hps hps , Handle to a presentation space.
USHORT hModule , Resource module handle; if the
resource is contained within the
exeoutable file, this parameter must be
assigned NULL; if the resource is in a
dynamic-link module, the parameter
must contain the module handle
returned by DosLoadModule.
USHORT idBitmap, The identifier assigned to the bitmap
within the resource file.
LONG Iwidth, The width in pixels to be given the
bitmap when it is copied into memory;
if 0, the bitmap is given its original
width.
LONG IHeight) ,. The height in pixels to be given the
bitmap when it is copied into memory;
if 0, the bitmap is given its original
height.

Return Value ..
The handle of the bitmap in memory, or the value
GPI ERROR if an error occurred.

• Figure 10.21..
The GPILoaLdB±t"aLp Presentation Manager function
® 522 Programmer's Guide to the os/2PresentationManager

WinDrawBitmap
Purpose,
Draws a bitmap within the specified presentation space.

Prototype..
BO0L APIENTRY WinDrawBitmap
(HPS hpsDst, Handle of the presentation space in
which the image is to be drawn.
HBITrm hbm, Handle of the bitmap to be drawn.
PRECTL pwrcsrc, Pointer to a RECTL structure (defined
in Figure 2.22) containing the
coordinates of the portion of the
bitmap that is to be drawn; if this
parameter is NULL, the entire bitmap
is drawn.
PPOINTL pptlDst, Pointer to a POINTL structure (defined
in Figure 3.28) containing the
coordinates of the point within the
presentation space where the lower
left corner of the bitmap is to be
placed; if, however, the f s flag
parameter contains the switch
DBM_STRETCH, this parameter
should point to a RECTL structure
containing the coordinates of the
rectangle that is to be ¢.JJcd with the
bitmap.
LONG clrFore, Foreground color to be used for
drawing the bitmap.
LONG clrBack, Background color to be used for
drawing the bitmap.

• Figure 10.22..
The W±nDrawB±t"ap Presentation Manager function
Creatinglcons,Bitmaps, and otherResources 523 .

USHORT fs) ,. Flags that specify how the bitmap is to


be drawn; you can choose from the
following values:

Value Effect
DBM NORMAL Bitmap drawn
normally
DBM n\IVERT Bitmap colors
inverted
DBM HALFTONE Bitmap drawnwith a
halftone pattern
DBM STRETCH Bitmap is stretched to
fill the rectangle
specified by the
pptlDst parameter,
which must point to a
RECTL structure

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

• Figure 10.22..
The WLnDra;wBLhaap Presentation Manager function (continued)

GpiDeleteBitmap
Purpose..
Frees a bitmap.

Prototype..
BOOL APIENTRY GpiDeleteBitmap
(HBITMAp hbm) ,. Handle of bitmap to be freed.

• Figure 10.23..
The GPIDcteteBit"aLp Presentation Manager function
• 524 Programmer's Guide to the os/2Presentation
Manager

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
When a process calls this function, it relinquishes its access to
the specified bitmap; the bitmap is not actually deleted until
all processes holding handles to the bitmap have called this
function.

• Figure 10.23..
The GPIDeleteBitmap Presentation Manager function ( continued)

The WM_DESTROY message is sent when the window is destroyed,


and is processed by the function Destroy. This function removes the bit-
map from memory through the following function call:

GpiDeleteBitmap
(HBitmap, '.

The WM_PAINT message is processed in the function Paint. As in


previous examples, this function obtains a handle to a presentation
space by calling WinBeginpaint and releases this handle through Win-
Endpaint. Also, as you have seen before, it calls WinQuerywindow-
Rect to obtain the coordinates of the current window in the RECTL
stmcture Rect. It then displays the bitmap through the following func-
tion call:

WinDrawBitmap
(Hpresspace, /* Presentation space handle. */
HBitmap, /* Bitmap handle from
/* GpiLoaaeitmap.
FILL ' /* Section of bitmap to draw:
/* NULL = ALL.
(PPOINTL ) &Rect , /* Pointer to rectangle to fill.
CLR NEUTFEL, /* Foreground color:
/* system default.
CLR BACKGROUND , /* Background color:
Creating Icons, Bitmaps, and Other Resources 525.

/* system default. */
DBM STRETCH) ,. /* Flag: */
/* fill rectangle with bitmap. */

Thethirdparametertothisfunctionspecifiesthecoordinatesofthepor-
tion of the bitmap that `is to be drawn; the value NULL causes the func-
tion to display the entire bitmap. The last parameter passes the value
DBM STRETCH; this flag forces the function to adjust the size of the
bitmap so that it fills the rectangular window area specified by
the fourth parameter. Since the fourth parameter is given the dimen-
sions of the client window obtained from WinQuerywindowRect, the
bitmap always fills the entire client window. When the system displays
the bitmap, it adds or subtracts pixels as necessary; as the user resizes
the window, the overall size and proportions of the bitmap change ac-
cordingly. Figure 10.24 illustrates the bitmap image displayed within
the client window; compare this figure with Figure 10.20, which il-
1ustrates the bitmap as it was originally designed in the Icon Editor.
Finally, the fifth and sixth parameters cause the bitmap to be drawn
using the default system foreground and background colors described

• Figure 10.24..
The bitmap as displayed by the program of Figure 10 .19
• 526 Programmer'sGuidetothe os/2Presentation
Manager

previously in the chapter (and hsted in Figure 2.23). Note that unlike
previous versions of this function, Paint does not bother to erase the
client window because the bitmap data always fill the entire window.

• OTHERRESOURCES
This final section discusses two additional Presentation Manager
resources: strings and programmer-defined resource types.

Strings
The Presentation Manager allows you to define a table of strings
within the resource script. Like other resources, the string table is inserted
into one or more resource segments within the executable file. The pro-
gramcansubsequentlycopyastringfromthistableintoaprogrambuffer,
anditcandisplayorotherwiseprocessthecontentsofthestring.
You can place the collection of program error messages, the program
name, or other constant string data within a string table rather than
defining the strings within the C source code. Defining all constant
strings within a string table is especially useful for applications that will
be translated into foreign languages. When such a program is trans-
lated, all strings, menu labels, and other language-specific items are
conveniently located within the resource script rather than dispersed
throughout the source code. Also, modifying the resource script does
not require recompiling the program, typically the slowest step in
building an application.
In the example application of Figures 10.15 through 10.19, presented
in the previous section, the program title is placed in a string table
rather than defined in the C source code. When the program runs, it
copies this string from the resource segment and passes it to the Win-
Createstdwindow function as the window title.
Creating Icons, Bitmaps, and OtherResources 527 .

The first step is to define the string table in the resource script. The
stringtableislabeledwiththekeywordSTRINGTABLEasshowninthe
following example, which defines three strings:

#define ID STRINGONE 0
#define ID-STRINGTWO 1
#define ID STRINGTHREE 2

STRINGTJreLE
BEGIN
ID STRINGONE, ``This is the first string"
ID STRINGTWO, ``This is the second string"
ID STRINGTHREE, ``This is the third string"
END

The three string identifiers in this example, ID_STRINGONE,


ID STRINGTWO, and ID_STRINGTHREE, are given unique values
and will be used to access the corresponding strings from the C pro-
gram.Allrequiredstringsmustbeplacedinthesamestringtable,since
you can define only a single string table in a resource file. Each string
has a maximum length of 255 characters.
Note that the system places up to 16 strings within a single resource
segment; if you define more than 16 strings in a given string table, the
system uses additional resource segments as required. The system
labels each resource segment based upon the identifiers of the strings
contained in the segment, according to the following formula:

resource label -- {string_identifier I 16) + 1

Therefore, for example, a string with the identifier 0 is placed in re-


source segment 1, and a string with the identifier 18 is placed in
resource segment 2. Accordingly, to minimize the number of segments
required, you should assign identifiers that are numbered consecutive-
ly begirming with a multiple of 16 (as in the preceding example).
• 528 Programmer'sGuidetothe os/2Presentation
Manager

WinLoadstring
Purpose..
Loads a string from a string table resource into a program
buffer.

Prototype..
SHORT APIENTRY WinLoadstring
(RE hab, Anchor block handle.
"ODULE hood, Resource module handle; if the resource is
contained within the exeoutable file, this
parameter must be assigned NULL; if the
resource is in a dynamic-link module, the
parameter must contain the module handle
returned by DosLoadModule.
USHORT id, Identifier assigned to the string in the
resource script.
SHORT cc"ax, Length of the receiving buffer.
PSZ pchBuffer) ,. The receiving buffer.

Return Value ..
The length of the string copied (excluding the terminating
NULL character; the maximum value is ccMax -1).

Notes..
The function copies at most ccMax - 1 characters and ap-
pends a NULL character to the end of the string in the receiv-
ing buffer.

• Figure 10.25..
The WinLoaLdshir\g Presentation Manager function

The example resource file given in Figure 10.17 defines a string table
containing a single string as follows:

STRINGTABLE
BEGIN
ID PROGNARE, "Bitmap Demo"
END
Creating Icons, Bitmaps, and OtherResources 529 .

You can call the Presentation Manager function WinLoadstring (Fig-


ure 10.25) to copy a given string from the resource segment into a pro-
grambuffer.TheexampleapplicationofFigure10.19callsthisfunction
to obtain the string containing the program title, immediately before
calling Wincreatestdwindow. The function call is as follows:

char ProgName [32] ,.


WinLoadstring
(HchcBlk, /* chchor block handle. */
NULL ' /* Module handle: in .EXE file.*/
ID PROGNRE, /* String identifier. */

::E:;::;;ogNane, , ;: ::::i::n:e:::¥::: buffer. :;


Note that you do 71of have to explicitly release a string resource, unlike
the other resources described in this chapter, since it is loaded into a
privateprogrambufferratherthanintoamemorysegmentmaintained
by the system.

Programmer-Defined Resource Types


In addition to resources belonging to the predefined resource types
discussed in this book, the Presentation Manager allows you to create
resourcesbelongingtoaprogrammer-definedtype.Theseresourcesper-
\,\, 1,

REHH you to insert data of an~arbitrary format into resource segments in


the program file. Such resources are declared in a resource script using
the following syntax:

RESOURCE t]pe_id nalrie_id resource_file

RESOURCE is the keyword that signifies a programmer-defined


resource type; fypc+.d is the resource type identifier; 71¢771c_I.d is the re-
source name identifier; and rcso#rccjz'Jc is the name of the file that con-
tains the resource data.
Note that all resource types have an associated resource type iden-
tifier; you do not normally need to include the type identifier when
declaring a resource belonging to a predefined type because the type is
implicit in the keyword that begins the definition. For example, the
• 530 Programmer's Guide to the os/2Presentation
Manager

keyword BITMAP implies a bitmap type resource, and you therefore do


not need to specify the type identifier (which is RT_BITMAP). When
creating a resource belonging to a programmer-defined type, however,
you must include a resource type identifier; as you win see, this iden-
tifier is subsequently used when the program accesses the resource. The
resource type identifier must be a value greater than 255.
The resource 71¢777c_z.d is analogous to the identifiers that are specified
when you declare resources belonging to predefined types such as bit-
maps. This identifier is also required when accessing the resource from
the program. There can be several resources of the same type, provided
that the names are unique; likewise, there can be several resources that
have the same name as long as the types are unique. In other words, the
combination of name and type must be unique for each resource.
FinaHy, the file specified in the declaration supphes the actual resource
data; this file can contain textual or binary data in any format that can be
understoodbytheappfication.Thefilecould,forexample,containthetext
required to implement a help utility. The fonowing is an example of the
definitionofaresourcethathasaprogrammer-definedresourcetype:

#define ID MYTYPE 256


#define ID-HELPTEXT 1

RESOURCE ID MYTYPE ID HELPTEXT HELP.TXT

In this example, the file HELP.TXT could be a file containing the text
that is displayed by a help utility.
To access the data belonging to a programmer-defined resource type
from your program, you must call the OS/2 kernel function DosGet-
Resource, which returns a selector to the segment containing the
resource data. This segment contains exactly the same data stored in the
file specified in the resource script. For example, the following call ob-
tains a selector that can be used to access the resource declared in the
previous example:

SEL SelRes,. /* Selector to memory segment */


/* containing resource. */
Creating Icons, Bitmaps, and Other Resources 531.

DosGetResource
(NULL, /* Module handle:
/* NULL means the .EXE file.
ID MYTYPE, /* Resource type identifier.
ID-HELPTEXT, /* Resource name identifier.
&S=lRes) ,. /* Address to receive resource
/* selector.

DosGetResource
Purpose..
Loads the specified resource segment into memory.

Prototype..
USHORT APIENTRY DosGetResource
("ODULE hood, :oe::aiLceedmw°}f#]ne thhaenedx[:¢ift:£:er:}i:,utrfes }S

parameter must be assigned NULL; if the


resource is in a dynamic-link module, the
parameter must contain the module handle
returned by DosLoadModule.
USHORT idType, The resource type identifier.
USHORT idName , The resource name identifier.
PSEL Psel) /. fh€d:eesi::yv:::a£Leentt°c:enctea±}V=::et£:1::::ru:cfe.

Return Value ..
0 if the function is successful, otherwise one of the following
error codes:

ERROR INVALID MODULE


ERROR INVALID SELECTOR
ERROR CANT FIND RESOURCE

• Figure 10.26..
The DosGetResoouce OS/2 kernel function
® 532 Programmer's Guide tothe os/2Presentation
Manager

Once you have obtained a selector to the segment containing the


resource data, you can use this selector to construct a far pointer to ad-
dress the individual data items. For example, the following code con-
structs a character pointer, PtrHelpText, which can be used to read the
individual characters of the help text:

PCH PtrHelpText,. /* Far character pointer to */


|* resc>nece dia:ta. *I

PtrHelpText = MAKEP (SelRes,0) ,. /* Construct far*/


/* poiriter. */
Note that the program is free to read or copy the data in the resource
segment,butmust#ofattempttowritetothissegment,sinceitisdesig-
nated as read-only (attempting a write operation would cause a protec-
tion violation). Also, you must be careful not to try to address beyond
the end of the resource segment (which would also cause a protection
violation). Fortunately, you can obtain the length of the segment in
bytes by calling the OS/2 kernel function Dossizeseg (Figure 10.27), as
follows:

ULONG Segsize,. /* Size of resource segment. */

Segsize = Dossizeseg /* Obtain segment size.


(SelRes, /* Selector from DosGetResource.
&Segsize) ,. /* Receives segment size.

Note also that programmer-defined resource types are manipulated


using basic OS/2 kernel function calls. Accordingly, these resource
types are available not only to Presentation Manager applications, but
also to other OS/2 protected mode programs.
Creating Icons, Bitmaps, andOtherResources 533 .

Dossizeseg
Purpose.:
\
Obtains the size in bytes of a memory segment.

Prototype..
USHORT APIENTRY Dossizeseg

::::N:e:|isLze) , ;Till:ncLtt:°r:t;;:t:he:rs;#F::I:i°ernetc:;Ve:LtfTeed
by the parameter sel.

Return Value ..
Zero if the function was successful, or a nonzero error code if
the function failed.

• Figure 10.27..
The DosS±zeseg OS|2 kernel function
ipter eleven

Adding a
Mouse Interface
535.

lthough the Presentation Manager does not require a


mouse, installing and using a mouse greatly simplifies

.Zr managing objects on the screen and issuing system and


program commands. The Presentation Manager auto-
matically provides- a mouse interface for the objects that it manages,
such as title bars, sizing frames, maximize and minimize boxes, menus,
and scroll bars. Accordingly, you can use the mouse to perform such
tasks as switching among applications, moving or adjusting the size
and shape of a window, issuing menu commands, and scrolling data
within a window. Presentation Manager applications gain the advan-
tageofthissystemmouseinterfacewithoutanyexplicitprogramming.
This chapter describes how you can extend this default mouse inter-
face by calling system functions and processing system messages that
allow you to control the mouse pointer and to act upon specific mouse
events. Most commonly, an application uses these facilities to manage
the mouse while the pointer is located within the client window. There-
fore, just as a program typically reads the keyboard while the client
window has the input focus, it can also explicitly handle the mouse
while the pointer is within the client window boundaries.
Note that the system automatically displays the mouse pointer on
the screen and moves the pointer image as the user moves the mouse
on the desk surface. An application is typically concerned with three
mouse parameters: the Zoc¢fi.o# of the mouse pointer within the win-
dow, the shape of the mouse pointer, and the status of the mouse b%f-
fo7is.Thischapterdiscusseseachofthesethreebasicparameters;thelast
section then describes how to use these facilities to implement a stand-
ard mouse interface.

FINDING THE
• MOUSE POINTERLOCATION
Before your program calls a Presentation Manager function to
deternine the mouse location or perform other explicit operations on
the mouse, it can call the WinQuerysysvalue function to determine
whether a mouse is installed. This function, described in Figure 11.1,
can be called to determine any one of a large number of system values.
•536 Programmer's Guide to the OS/2 Presentation Manager

You request a specific system value through the second parameter


(SHORT isysvalue), and WinQuerysysvalue returns this value direct-
ly to the calling program. A list of identifiers for the possible system
values is given in Table 11.1; note that WinQuerysysvalue supplies
dimension values in pixel units and time values in milliseconds. To
determine whether the mouse is installed, you pass the identifier
SV_MOUSEPRESENT, and WinQuerysysvalue returns TRUE if a
mouseisinstalledorFALSEifthereisnomouse.Theexampleprogram

WinQuerysysvalue
Purpose..
Returns the specified system value.

Prototype..
LONG APIENTRY WinQuerysysvalue
(HWND hwndDesktop, The value HWND DESKTOp to
identify the deskto-p window.
SHORT isysvalue) ,. The identifier of the desired system
value; the constants for these
identifiers have the SV_ prefix and are
listed in Table 11.1.

Return Value..
The requested system value, or 0 if an error occurred.

Notes..
Some of the system values can be set through the function
Winsetsystemvalue.

RelatedFunctions..
Winsetsystemvalue

• Figure 11.1..
TheW±r\QuerysyswahaePresentationManagerfunction
Adding a Mouse Interface 537.

listed in Figure 11.14 and described in the next section tests whether a
mouse is present, as follows:

if ( !WinQuerysysvalue
(HEED DESKTOP,
SV MOUSEPRESENT) )
E-rrorQuit ("Program requires mouse'') ,.

A window procedure can determine the position of the mouse


pointer within its window using one of two basic methods. First, it
can call the WinQuerypointerpos function (Figure 11.2) or the Win-
QueryMsgpos function (Figure 11.3) to obtain the pointer position at
any time it requires this information. Alternatively, it can process the
WM MOUSEMOVE message, which is sent to the client window pro-
cedure each time the position of the pointer changes ¢77d the pointer is
located within the client window.
WinQuerypointerpos returns the current position of the mouse ir
scrcc# coordz.7i¢fcs; screen coordinates are the horizontal and vertical posi-
tions of the mouse relative to the lower left corner of the desktop win-
dow (the entire screen). You can convert screen coordinates into
coordinates relative to a specific window by calling the WinMap-
Windowpoints Presentation Manager function (Figure 11.4). It is general-
ly easiest to work with coordinates that are relative to the chent window.
As an example, the fouowing code obtains the current screen coordinates
ofthemousepointerandthenconvertsthesevaluesintocoordinatesrela-
tive to the chent window:

Hue Hclient,.
POINTL Mouseposition,.

WinQuerypointerpos
(HIND DESKTOP, /* Desktop window handle.
&Mous=Position) ,. /* Address of POINTL structure.

WinMapwindowpoints
(HEED DESKTOP, /* Existing coordinate space.
Hclient' /* Desired coordinate space.
• 538 Programmer's Guide to the os/2 Presentation
Manager

&Mouseposition, /* Address of p0INTL array. */


1),. /* Only one element in array. */

ThisexampleassumesthatthevariableHclientcontainstheclientwin-
dow handle (returned by Wincreatestdwindow). After the call to Win-
Mapwindowpoints, the structure Mouseposition contains the current
position of the mouse in pixel units, relative to the lower left corner of
the client window. Conveniently, this position is specified in the same
units and is relative to the same coordinate system that has been used
when calling such functions as GpicharstringAt, WinlnvalidateRect,
and WinDrawBitmap in previous examples in the book.

• Table 11.1.. System Value Jifentifters

Identifier Value Systemvalue


*sv swAPBurTON
Flag indicating whether
mouse buttons are
swapped
*SV DBLCLKTIME
Mouse double-click time
*SV CXDBLCLK
Width of mouse double-
click sensitive area
*SV CYDBLCLK
Height of mouse double-
click sensitive area
SV CXSIZEBORDER Width of sizing border
SV CYSIZEBORDER Height of sizing border
*SV ALARM
Flag indicating whether
alarm sound generated
by WinAlarm (Figure
6.9) is enabled
*SV CURSORRATE
Cursor blink rate
SV FIRSTSCROLLRATE Delay before autoscroll-
ing starts when using a
scroll bar
SV SCROLLRATE 11 Delay between scroll
operations when using a
scroll bar
AddingaMouselnterface 539 .

• Tablet:1.1.. S stem Value Identi (continued)

Identifier Value System value


SV NUMBEREDLISTS 12 Flag indicating whether
the system automatically
numbers selection lists
such as pull-down
menus and groups of
radio buttons
*SV WARNINGFREQ 13 Frequency of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_WAENING flag
*SV NOTEFREQ 14 Frequency of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_NOTE flag
*SV ERRORFREQ 15 Frequency of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_ERROR flag
*SV WARNINGDURATION 16 Duration of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_WAENING flag
*SV NOTEDURATION 17 Duration of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_NOTE flag
*SV ERRORDURATION 18 Duration of sound
generated by passing
WinAlarm (Figure 6.9)
the WA_ERROR flag
SV CXSCREEN Width of screen
SV CYSCREEN Height of screen
• 540 Programmer's Guide to the os/2Presentation
Manager

• Tablell.1.. S stem Value Identi (continued)

Identifier Value Systemvalue


SV CXVSCROLL 22 Width of vertical scroll
bar
SV CYHSCROLL 23 Height of horizontal
scroll bar
SV CYVSCROLLARROW 24 Height of vertical scroll
bar arrow
SV CXHSCROLLARROW 25 Width of horizontal
scroll bar arrow
SV CXBORDER 26 Width of normal win-
dow border
SV CYBORDER 27 Height of normal win-
dow border
SV CXDLGFRAME 28 Width of dialog box
border
SV CYDLGFRAME Height dialog box border
SV CYTITLEBAR Height of title bar
SV CYVSLIDER Height of vertical scroll
bar slider
SV CXHSLIDER 32 Width of horizontal
scroll bar slider
SV CXMINMAXBUTTON 33 Width of minimize/maxi-
mize button
SV CYMINMAXBUTTON 34 Height of minimize/max-
imize button
SV CYMENU 35 Height of menu bar
SV CXFULLSCREEN 36 Width of client window
when window is maxi-
mized
SV CYFULLSCREEN 37 Height of client window
when window is maxi-
mized
Adding a Mouse Interf ace 541.

• Tablell.1.. S stem Value Identi (continued)

Identifier Value Systemvalue

SV CXICON Width of icon


SV CYICON Height of icon
SV CXPOINTER Width of pointer
SV CYPOINTER Height of pointer
SV DEBUG Flag indicating debug
version

SV CMOUSEBUTTONS Number of mouse but-


tons (0 if no mouse is
installed)

SV POINTERLEVEL 44 Pointer hide level (0 is


visible)

SV CURSORLEVEL 45 Cursor hide level (0 is


visible)

SV TRACKRECTLEVEL 46 Tracking rectangle hide


level (0 is visible)

SV CTIMERS 47 Number of available


timers
SV MOUSEPRESENT 48 Flag indicating whether
mouse is installed

* Marks value that can be set theough Winsetsysvalue

Note that the coordinates used to specify the mouse pointer position
are actually the coordinates of a single pixel within the pointer known
as the feof spot . The hot spot within the standard arrow pointer, for ex-
ample, is the pixel at the tip of the arrow. As mentioned in Chapter 10,
you must designate the hot spot when designing a custom pointer
using the Icon Editor.
The function WinQueryMsgpos also returns the position of the
mouse pointer in screen coordinates. This function, however, does 7iof
• 542 Programmer's Guide to the os/2Presentation
Manager

WinQuerypointerpos
Purpose..
Obtains the current position of the mouse pointer in screen
coordinates.

Prototype..
BOOL APIENTRY WinQuerypointerpos
(HWND hwncoesktop, The value HWND DESKTOp to
identify the deskto-p window.
ppolNTL pptl) ,. Pointer to a POINTL structure (defined
in Figure 3.28) that is assigned the
current coordinates of the mouse
pointer hot spot in screen coordinates.

Return Value ..
TRUE if the function is successful, or FALSE if an error
occurred.

Notes..
Thisfunctiongivesthehorizontalandverticalpositionofthe
mouse relative to the lower left corner of the screc71; to con-
vert these values to coordinates relative to the lower left
corner of a given zuz.7idoz47, you can call WinMapwindow-
Points. You can call Winsetpointerpos to scf the current
position of the pointer.

RelatedFunctions..
WinMapwindowpoints (Figure 11.4)
WinQueryMsgpos (Figure 11.3)
Winsetpointerpos (Figure 11.11)

• Figure 11.2..
The WinQuerypoLulerpos Presentation Manager f unction
Adding a Mouse Interface 543.

WinQueryMsgpos
Puxpose..
Obtains the position of the mouse pointer at the time the last
message extracted from the message queue was posted. The
position is given in screen coordinates.

Prototype..
BOOL APIENTRY WinQueryMsgpos
(HAB hab, Anchor block handle.
ppolNT[. pptL ) '. E[Pin::r3t.28a) :h°a[t¥sT:s::r£Ce¥:a:dceo%::iFtes
of the mouse pointer hot spot.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
To obtain the ct/77e71f pointer position, call the function Win-
Querypointerpos. WinQueryMsgpos gives the horizontal
and vertical position of the mouse relative to the lower left
corner of the scrce7t; to convert these values to coordinates
relative to the lower left comer of a given zt7i.71doztJ, you can
call WinMapwindowpoints.

Rel,ated Functions ..
WinMapwindowpoints (Figure 11.4)
WinQuerypointerpos (Figure 11.2)

• Figure ll.3..
The WinQuery:Msgpos Presentation Manager function
• 544 Programmer's Guidetothe os/2Presentation
Manager

WinMapwindowpoints
Purpose..
Maps the coordinates of one or more points from the coor-
dinate space relative to one window into the coordinate
space relative to another window.

Prototype..
BOOL APIENTRY WinMapwindowpoints
(HWND hwndFrom, Handle of the windowfro777 whose
coordinate space the coordinates of the
points are to be mapped; the value
HWND_DESKTOP indicates that the points
are given in screen coordinates.
Hum hwndTo, Handle of the window fo whose coordinate
space the coordinates of the points are to be
mapped; the value HWND DESKTOP
indicates that the points are-to be converted
into screen coordinates.
PPOINTL pptl, Pointer to an array of POINTL structures
(defined in Figure 3.28) containing the
coordinates of the points that are to be
mapped.
SHORT cwpt) ,. The number of POINTL structures in the
array pointed to by the pptl parameter.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
Since a RECTL structure (defined in Figure 2.22) is equi-
valent to two contiguous POINTL structures, you can con-
vert the coordinates contained in a RECTL structure by
setting pptl to the address of this structure and assigning
cwpt a value of 2.

• Figure 11.4..
The W±r\Mapwindowpoints Presentation Manager function
AddingaMouselnterface 545 .

return the current position; rather, it returns the position of the pointer at
the time the last message obtained from the message queue was posted.
RememberfromChapter2(inthesectionentitledGetandDispatchMes-
sages) that all messages in the message queue contain the position of
the mouse at the time the message was posted (the mouse position is the
sixth and last field of the QMSG structure). When your program calls
WinDispatchMsg to dispatch a message, the system calls the ap-
propriate window procedure, but does not pass this procedure the
mouse position (it passes only the first four fields of QMSG). By calling
WinQueryMsgpos, however, the window procedure can obtain this
position.
The second basic method for the window procedure to obtain the
mouse position is by processing the WM_MOUSEMOVE message (Fig-
ure 11.5). This message is sent whenever the mouse position changes,
and it is accompanied by the new coordinates of the mouse position.
Note that WM MOUSEMOVE is normally sent only to the window
directly below-the mouse pointer (unless a window procedure has
called Winsetcapture, which forces the system to send all subsequent
mouse messages to the specified window regardless of the location of
the pointer). Note also that the coordinates supplied by this message are
relative to the receiving window, and therefore they do not have to be
remapped from screen coordinates. The example programs given in the
following two sections illustrate the use of the WM_MOUSEMOVE
message.
The choice of basic methods for obtaining the mouse pointer posi-
tion+alling a function or processing a message+depends upon the
requirements of the application. Calling WinQuerypointerpos provides
themostcurrentpositionvalue(thewindowprocedurecannotreceivead-
ditional WM_MOUSEMOVE messages until it finishes processing the cur-
rent message; if the user is moving the mouse while a message is being
processed, the value supplied by the last WM_MOUSEMOVE message
may no longer be valid). Obtaining the mouse position by processing the
WM_MOUSEMOVE message, however, has several advantages. First, this
method is more in conformance with the message-based architecture of a
PresentationManagerapplication,anditfreestheprogramfromhavingto
exphcitly poll the system for the mouse position. Also, the coordinates
provided by this message are already relative to the client window, and
•546 Programmer's Guide to the OS/2 Presentation Manager

therefore do not have to be remapped. Finally, as you win see in the ex-
ample programs in the fonowing sections, this message provides a con-
venient signal indicating that the mouse pointer is ourrently located
within the chent window.

WM MOUSEMOVE
Purpose..
This message is sent by the system to the window beneath
the mouse pointer (or to the mouse capture window, if any)
each time the position of the mouse pointer changes.

Parameters..
REAEN mpl
low-order word: The horizontal pointer coordinate
relative to the lower left corner of the
window.
high-order word: The vertical pointer coordinate relative
to the lower left corner of the window.
REZuRAI mp2
low-order word: The result returned from a
WM_HITTEST message, or 0 if a
mouse capture is in progress.
high-order word: 0.

Return Value ..
The window procedure should return TRUE if it has
processed the message, or FALSE if it has not processed the
message.

• Figure 1.1.5..
The WM_MOUSEMOVE Presentation Manager message
AddingaMouselnterface 547 .

SETTING THE
• MOUSE POINTERSHAPE
The default mouse pointer automatically displayed by the system
is the standard single-headed, slanted arrow. You can force the sys-
tem to display an alternative pointer by calling the Presentation
Manager function Winsetpointer (Figure 11.6). Once you call this func-
tion, passing it the handle of the desired pointer, the system uses this
pointer until the function is subsequently called to specify another
pointer.
When you call Winsetpointer you can specify the handle of a pointer
providedbythesystem,orthehandleofacustompointerthatyouhave
created using the Icon Editor. To obtain the handle of one of the pointers
provided by the system, you can call the Presentation Manager function
WinQuerysyspointer (Figure 11.7), passing the identifier of the desired

Winsetpointer
Purpose..
Sets the mouse pointer that is displayed by the system.

Prototype..
BOOL APIENTRY Winsetpointer
(HWND hwndDesktop , The desktop window handle,
HWND DESKTOP.
HpolNTER hptrNew) ,. The handle of the new pointer; if this
value is NULL, the pointer is removed
from the screen.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

• Figure 11.6..
The Winsetpoinler Presentation Manager function
•548 Programmer's Guide to the OS/2 Presentation Manager

pointer as the second parameter. Note that the identifiers listed in Fig-
ure 11.7 include eight standard mouse pointers as well as five standard
icons. The system mouse pointers are illustrated in Figure 11.8, and the
system icons are illustrated in Figure 11.9 (both the icons and the
pointers are labeled in these figures using the identifiers that are passed
to WinQuerysyspointer). Since the data structure for a pointer is the
same as that for an icon, you could easily pass one of the system icon
handles to Winsetpointer to install the icon as the current mouse
pointer. However, the icons make rather awkward-looking pointers,
and they are best displayed as stationary objects within the client win-
dow using the WinDrawpointer function (Figure 10.9). The example
program in Figure 11.14, explained later in this section, displays each of
the standard system pointers.

WinQuerysyspointer
Purpose..
Returns the handle to the requested system pointer or icon.

Prototype..
HPOINTER APIENTRY WinQuerysyspointer
(HWND hwncoesktop, The value HWND DESKTOp to
identify the deskto-p window.
SHORT iptr, Identifier of the system pointer
desired; you can choose from the
following list:

Identifier Pointer/Icon
SPTR ARROW Standard arrow
pointer
SPTR TEXT I-beam pointer
SPTR WAIT Hourglass pointer
SFTR MOVE Move pointer
SFTR SIZENWSE Double-headed
arrow, sloping from
upper left to lower
right

• Figure ll.7..
The WinQuerysysp oLriter Presentation Manager function
Adding a Mouse Interface 549.

SPTR SIZENESW Double-headed


arrow, sloping from
upper right to lower
left
SFTR SIZEWE Horizontal
double-headed arrow
SFTR SIZENS Vertical
double-headed arrow
SPTR APPICON Standard application
icon
SPTR HANDICON Hand icon
SPTR_QUESICON Question-mark icon
SPTR BANGICON Exclamation-mark
icon
SFTR NOTEICON Asterisk icon

BOOL fLoad) ,. If this parameter is TRUE, the function


creates a new copy of the system
pointer and returns the handle to this
copy; if the parameter is FALSE, the
function returns the handle to the
system pointer itself .

Return Value ..
The pointer handle.

Notes..
If you assign fLoad a value of TRUE, you will obtain a new
copy of the system pointer; you should select this option if
you need to modify the pointer. If you assign FALSE to
fLoad, you will obtain a handle to the system's copy of the
pointer;notethatanattempttodisplaythispointer(through
Winsetpointer, for example) will fail if another process is
currently accessing the same pointer.

Related Functions ..
Winsetpointer (Figure 11.6)

• Figure 11.7:
Tire WinQuerysyspoir\+er Presentation Manager function ( continued)
®550 Programmer's Guide to the OS/2 Presentation Manager

Alternatively, you can pass Winsetpointer the handle of a custom


pointer that you have created in the Icon Editor, converted into a pro-
gram resource, and then loaded using the WinLoadpointer Presenta-
tion Manager function. The techniques for designing a custom pointer
were described in Chapter 10, in the section entitled Designing a Mouse
Pointer. Also, these techniques are illustrated by the example program
of Figure 11.21, which installs a custom mouse pointer and is described
later in the chapter.

EF ®¢
SFTR SIZENWSE SFTFI SIZENESW SFTR SIZEWE SFTR SIZENS

fe I RI ®
SFTR AFIROW SFTFI TENT SFTR WAIT SFTR MOVE

• Figure 1:1.8..
The system mouse pointers

• Figure 1.1.9..
The system icons
AddingaMouselnterface 551 .

Note that when your application has completed displaying a mouse


pointer (either a system pointer or one you have created), you can
release the pointer handle by calling WinDestroypointer (Figure 10.10).
Now that you have seen feozo to set the mouse pointer displayed by
the system, the next question is zufec7i to display a specific pointer. Typi-
cally, an application will set the mouse pointer according to one of two
criteria. First, a program may select a mouse pointer according to the
current position of the pointer. The simplest example is an application
that selects a certain mouse pointer whenever the pointer is located
within the client window. The example application in Figure 11.21
(described in the section on Reading the Mouse Buttons) sets the mouse
pointer to a custom pointer (a paintbrush created in the Icon Editor)
whenever the pointer is located within the client window. This task is
performed by simply calling the Winsetpointer function each time the
WM_MOUSEMOVE message is received, as follows:

HPOINTER HMouseptr,.

case WM MOUSEMOVE :

Winsetpointer
(rmun DESKTop ,
HMous=Ptr) ,.

As you will see later in the chapter, HMouseptr contains the handle
of the custom mouse returned by WinLoadpointer. The WM_MOUSE-
MOVE message is sent to the client window when the mouse pointer
first enters the window, and subsequently each time the pointer moves
within the window. When the pointer leaves the client window, these
messages are sent to the new underlying window, which presumably
sets the pointer to another appropriate shape. It may seem inefficient to
continually reset the pointer to the s¢77zc value as it moves to various
positions within the client window; however, the Microsoft documenta-
tion indicates that this function is very fast when the specified pointer is
the same as the current pointer. (Unfortunately, the system does not
• 552 Programmer's Guide to the os/2PresentationManager

provide messages that are sent only when the mouse enters or leaves
the client window.)
An application can also set the pointer to various shapes depending
upon the specific position of the mouse pointer within the client win-
dow. For example, an application might display the I-beam system
pointer (identified by the value SPTR_TEXT) in a section of the client
window containing text. To demonstrate this technique, the example
program of Figure 11.14 displays one of the eight standard system
pointers depending upon which section of the client window currently
contains the mouse pointer. See the description of this program later in
this section.
A second possible criterion for selecting the mouse pointer shape is
the` current program activity. For example, while the program is execut-
ing a lengthy operation, during which it cannot accept user input, it
could display the hourglass system icon (identified by the value
SPTR_WAIT). Also, a program currently engaged in moving an object
might display the 771oz7c icon (SPTR_MOVE, shown in Figure 11.8).
Note that an application can display and move a mouse pointer even
if a mouse is not installed. For example, in the absence of a mouse, a
program might nevertheless display the hourglass mouse pointer to in-
dicate a pause in input. Another example is a drawing program that
uses the mouse pointer to indicate the drawing position; if a mouse
were not installed, the program could still display the pointer, but
would have to explicitly move the pointer in response to keyboard
input. You can use the following steps to display and move a pointer in
the absence of a mouse (the previous section in this chapter described
how to determine whether a mouse is installed):

• Call the function winshowpointer (Figure 11.10) to cause the


system to display the mouse pointer. (If a mouse is installed, the
system automatically displays the pointer; if, however, a mouse
is not installed, you can coax the system into displaying a
pointer by calling Winshowpointer.)
AddingaMouselnterface 553 .

Winshowpointer
Purpose..
Shows or hides the mouse pointer by changing the pointer
hide level.

Prototype..
BOOL APIENTRY Winshowpointer
(HWND hwndDesktop, fdheeny±a#ehE¥¥kpo-pD::nKdTo°w? t°

BooL f show ) ,. [dfetchr±esmv:i#: t±ieTFOT:{etrhfi:en|CetiJ°eT; if

the value is FALSE, it increments the


hide level.

Return Value ..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
If the pointer hide level is 0, the mouse is displayed; if it is
greater than 0, the mouse is hidden. If a mouse is installed,
the system assigns the hide level an initial value of 0 (which
shows the pointer); if no mouse is installed, the system as-
signs an initial value of 1 (which hides the pointer). The hide
level is not allowed to go below 0 (therefore, calling this
function with f show equal to TRUE when the mouse is al-
ready visible has no effect). You can obtain the current hide
level by calling WinQuerysysvalue, passing an identifier of
SV POINTERLEVEL as the second parameter.

Related Functions ..
WinQuerysysvalue (Figure 11.1)

• Figure 11.10..
The WinshowpoLuler Presentation Manager function
•554 Programmer's Guide to the OS/2 Presentation Manager

• Call winsetpointerpos (Figure 11.11) to set the location of the


pointer. (If a mouse is installed, the user and the system set the
position of the pointer; if no mouse is installed, your program
must explicitly set the position.) Note that in the same manner as
WinQuerypointerpos, the location is specified in screen coor-
dinates; you can call WinMapwindowpoints, if necessary, to
generate screen coordinates from coordinates relative to the
client window.

Winsetpointerpos
Purpose..
Sets the position of the mouse pointer.

Prototype..
BOOL APIENTRY Winsetpointerpos
(IIWND hwndDesktop, The value HWND DESKTOp to
identify the deskto-p window.
SHORT x, The horizontal position of the pointer
in screen coordinates.
SHORT y) ,. The vertical position of the pointer in
screen coordinates.

Return Value ..
TRUEifthefunctionwassuccessful,orEALSEifanelTororcuned.

Notes..
The mouse position for this function, like the function Win-
Querypointerpos, is specified in screen coordinates (which
are relative to the lower left corner of the screen). You can call
WinMapwindowpoints to convert window relative coor-
dinates to screen coordinates.

Relate d Functions ..
WinMapwindowpoints (Figure 11.4)
WinQuerypointerpos (Figure 11.2)

• Figure ll.11..
The WLnsetpointerpos Presentation Manager f unction
AddingaMouselnterface 555 .

The example program in Figure 11.14 illustrates the techniques for


obtaining a handle to a system pointer, and for assigning a pointer
shape according to the current pointer position in the client window.
Specifically, the program obtains a handle for each of the eight system
mouse pointers illustrated in Figure 11.8. It then conceptually divides
the client window into eight rectangles of approximately equal size;
as the user moves the mouse pointer into each division, the program as-
signs a different mouse pointer. For example, the normal arrow pointer
is displayed when the pointer is in the lower left quadrant, and the 1-
beam pointer is displayed when the pointer is in the next quadrant, to
the right in the bottom row. This program thus gives you an oppor-
tunity to see each of the system pointers, one at a time. Figure 11.12
provides a MAKE file for preparing this program, and Figure 11.13 con-
tains the linker definition file.

Figure 11.12
This MAKE file prepares the program of Figure 11.14
#
FIG1114.OBJ : FIG1114.C
€1 /W2 /c /Zp /E2ws FIGll_14.C

FIG1114.EXE : FIG1114.OBT FIG1113.DEF


link /NOD FIGll-14.OEL, , NULT OS2.LIB SLIBCE.LIB, FIGll_13.DEF

• Figure 11.,12..
A MAKE file for preparing the progran of Figure 11.14

; :i:==:: 3efinition file for the program listed in Figure 3


FIGll 12

1024
8192
Wndproc

• Figure 11.13..
A linker definition file for the program of Figure 11.14
• 556 Programmer's Guide to the os/2 Presentation Manager

/*
Figure 11.14

This program obtains handles to each of the 9 system pointers. Each of


these pointers is displayed as the mouse enters a specific quadrant of
the window (the window is conceptually divided into 9 quadrants) .
*/
#def ine INCL WIN
#include <OSZ.H>
#include <stdio.h>
#include <process.h>

¥:i: ::::r?::: i:::=c:¥:;;age) ; /: ::::n:::°:h:e::ag=6g=::.Program.


mESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;

mB HAncBlk; /* Anchor block handle.


END HFrame; /* Frame window handle.
I"Q HMesQue; /* Message queue handle
void main ()
(
HWND Hclient; /* Client window handle.
QMSG QueMess; /* Message queue structure.
ULONG CtlData = /* Control windows to include.
FCF MINmx /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* Display program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
HAncBlk = Winlnitialize /* Returns an anchor block handle. */
(0); /* Initialization options: must be 0. */
HMesQue = WincreateMsgQueue /* Returns a message queue handle. */
(HAncBlk, /* Anchor block handle. */
0); /* Minimum queue size: 0 means default size.*/
WinRegisterclass /* Register a window class.
(HAncBlk,
''mlN„ , /* Anchor block handle.
/* Window class name.
Wndproc , /* Window procedure associated with class.
OL, /* Class style: no styles specified.
0); /* Bytes of data storage for each window.
HFrame = Wincreatestdwindow /* Create a standard window collection.
Parent window handle.
Frame window style.
i::I:E::;E:Op
„MAIN„ ,
' ; /*; Address of control data.
Client window class name.
'': System Pointer Demo", /* Text for title bar.
OL, /* Client window style: none specified.

• Figure 11.14..
A program that displays the system mouse pointers
AddingaMouselnterface 557 .

0' /* Resource module handle: none.


0, /* Resource identification: none
&Hclient) ; /* Address to receive client window hand.
while (WinGetMsg /* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess , /* Address of message structure.
0, /* Window filter: any window.
0, /* First message identifier: n/a.
0)) /* Ijast message identifier: n/a.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

Quit (0); /* Exit program with 0 error level.


} /* end main */

/*** The window procedure and subroutines. ***********************************/

#RE§g:: EX:E#:R¥ S:::::y (E##B :#::; 8§E8R: ::g; #:£¥ :::; #:£¥ :S2) ;
MRESULT EXPENTRY MouseMove (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2) ;
*/
HPOINTEF HandleTable [4][2]; /* Array for holding 8 pointer handles.
*/
static SHORT xQuart; /* 1/4 horizontal dimension of window. */
static SHORT yHalf ; /* 1/2 vertical dimension of window.
MRESULT EXPENTRY Wndproc */
(HWND hwnd, /* Window handle. */
USE.[ORT msg, /* The message. */
MPAEN mpl, /* Message-specific information. */
MPARI" mp2) /* Message-specific information.
(
switch (msg)
(
case WM CREATE:
return Create (hwnd,msg,mpl,mp2) ;
case WM DESTROY:
return Destroy (hwnd,msg,mpl,mp2) ;
case WM ERASEBACKGROUND: /* Have the system erase the window. */
return TRUE;
case WM MOUSEMOVE:
return MouseMove (hwnd,msg,mpl,mp2) ;

case WM SIZE:
return Size (hwnd,msg,mpl,mp2`},``

default: /* Perform the default processing on all other messages. */

• Figure 11.14..
A:;program that displays the system mouse pointers (continued)
• 558 Programmer's Guide to the os/2 Presentation
Manager

return WinDefwindowproc (hwnd,msg,mpl,mp2) ;


)

} /* end Wndproc */

MRESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/* Test for presence of mouse; quit if no mouse is installed.
if ( !WinQuerysysvalue
(HIND DESKTOP,
SV_M06SEPRESENT ) )
ErrorQuit ("Sorry, you must have a mouse.") ;

/* Obtain handles for the 9 system pointers.


HandleTable [0] [0] = WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR-ARROW, /* Normal arrow pointer.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [0] [1] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR TEXT, /* Text I-beam.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [0] [2] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR whlT, /* Hour-glass pointer.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [0] [3] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR riovE, /* Move pointer.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [1] [0] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR glzENWSE, /* Downward sloping, double-headed.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [1] [1] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR 5IZENESW, /* Upward sloping, double-headed.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [1] [2] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR glzEWE, /* Horizontal, double-headed.
FALSE) ; /* Do not make a new copy of pointer.
HandleTable [1] [3] WinQuerysyspointer
(HWND DESKTOP, /* Desktop window handle.
SPTR glzENS, /* Vertical, double-headed.
FALSE) ; /* Do not make a new copy of pointer.
return FALSE;

} /* end Create */

MRESULT EXPENTRY Destroy (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(

• Figure 11.14..
A progran that displays the syste:in mouse pointers (continued)
AddingaMouselnterface 559 .

register int i,j;


/* Release handles for the 8 system pointers.
for (i-0;i=-1;++i)
for (j-0;j<-3;++j)
WinDestroypointer
(HandleTable [i] [j ] ) ;

} /* end Destroy */

MRESULT EXPENTRY MouseMove (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/* Assign one of the 8 pointers depending upon the window quadrant
containing the mouse.
Winsetpointer
(HWND DESKTOP,
HandlETable [MOUSEMSG(&msg) ->y / yHalf]
[MOUSEMSG(&msg)->x / xQuart]) ;
return TRUE;

} ,/* end MouseMove */

MRESULT EXPENTRY Size (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/* Save dimensions of a single quadrant.
xQuart = SHORTIFROMMP (mp2) / 4 + 1;
yHalf = SHORT2FROMMP (mp2) / 2 + 1;

return FALSE;

} /* end Size */

void ErrorQuit /* Terminate program due to fatal error condition. :/


*/
(char-*Message) /* Error message to display to user.
(
char Buffer [60];

sprintf (Buffer,"Program Error: %s",Mes'sage) ;


WinMessageBox /* Display a message box.
(HWND DESKTOP, /* Handle of parent: desktop window.
HFrame, /* Handle of owner: frame window.
Buffer, /* Message text.
''Pointer Demo", /* Caption.
0, /* Help window ID: not needed.
MB_OK I /* Display an 'OK' button.
MB ICONHEND) ; /* Display a hand icon.
Quit (1); /* Call normal termination function.
} /* end ErrorQuit */

• Figure 11.14..
A prograiii that displays the system mouse pointers (continued)
®560 Programmer's Guide to the OS/2 Presentation Manager

void Quit (int Errorcode)


(
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue) ;
WinTerminate (HAncBlk) ;
exit (Errorcode) ;
) /* end Quit */

• Figure ll.14..
A progran that displays the system mouse pointers (continued)

The program obtains handles to each of the system pointers by call-


ing WinQuerysyspointer (Figure 11.7) during processing of the
WM_CREATE message. These handles are stored in the two-dimen-
sional array HandleTable (the first dimension corresponds to the row
in which the pointer will be displayed, and the second dimension cor-
responds to the column). These handles are later released by calling
WinDestroypointer (Figure 10.10) during processing of the WM_DES-
TROY message (which is sent when the window is removed).
The function Size, activated through the WM_SIZE message (Figure
3.22), maintains the global variables xQuart and yHalf, which store the
horizontal and vertical sizes of a single quadrant; each quadrant is ap-
proximately one-quarter the current width of the window and one-half the
height. These values are caloulated through the fouowing expressions:

xQuart = SHORTIFRchn@
yHalf = SHORT2FROMMP

Remember that the low-order word of mp2 contains the horizontal size
of the client window, and the high-order word contains the vertical size.
(The + 1 terms in these expressions prevent addressing beyond the
bounds of the HandleTable array in the function call to Winsetpointer,
explained next. Note that the eight quadrants into which the window is
divided are only ¢pproxz.771¢£cJy equal.)
Finally, the function that processes the WM_MOUSEMOVE function
calls Winsetpointer to set the mouse pointer according to the specific
AddingaMouselnterface 561 .

screen quadrant currently containing the pointer. This function call is


as follows:

case WM MOUSEMOVE:

Winsetpointer
(HEED DESKTOP,
Handl=Table [MOUSEMSG(&msg) ->y / yHalf]
[MOUSEMSG(&msg) -> x / xQuart] ) ,.

Note that the MOUSEMSG macro is analogous to the CHARMSG and


COMMANDMSG macros, and provides a convenient method for
extracting both the vertical (MOUSEMSG(&msg)->y) and horizontal
(MOUSEMSG(&msg)->x) coordinates of the mouse pointer.
Note also that the window procedure does not contain a proce-
dure for processing the WM_PAINT message, which normally per-
forms the task of erasing the client window (that is, filling it with the
background color) each time this window becomes invalid. Rather,
the client window procedure forces the system to erase the window
by simply returning TRUE whenever it receives the WM_ERASE-
BACKGROUND message (Figure 11.15). Returning TRUE from this
message is an easy and efficient method for erasing the client window;

WM ERASEBACKGROUND
_

Purpose..
This message is sent to the client window so that the client
window procedure can either erase the window itself, or
have the system erase the window using the default back-
ground color (CLR_BACKGROUND).

• Figure 11.15..
Tfie WM ERASEBACKGROUND Presentation Manager message
• 562 Programmer's Guide to the os/2 Presentation
Manager

Parameters..
REAIRAI mpl Handle to a presentation space that can be
used to erase the window if the client
window procedure chooses to perform this
operation.
REAEN mp2 Address of a WRECT structure (defined
below) containing the dimensions of the
rectangle to be erased.

Structure..
typedef struct WRECT
(
SHORT xLeft,.
SHORT durmyl ,.
SHORT yBottom,.
SHORT durmy2 ,.
SHORT might,.
SHORT durmy3 ,.
SHORT yTop,.
SHORT dumy4 ,.
)
WRECT,.

Return Value ..
The client window procedure should return TRUE to force
the system to erase the window; it should return FALSE if it
has performed the erasing operation itself.

Notes..
Returning TRUE from this function is an efficient method for
erasing the client window. The message is sent by the frame
window procedure whenever the frame window is in-
validated (it is sent by the routine that processes the
WM_PAINT message); the message is therefore 7iof sent
when the client window alone is invalidated.

• Figure ll.15..
The WM_ERASEBACKGROUND Presentation Manager message (continued)
AddingaMouselnterface 563 .

however, since the message is sent only when the fr¢771e wz.71do" is in-
validated, the technique would fail if the client window alone were in-
validated (for example, the text editor presented in the first part of this
bookfrequentlycallsthefunctionWinlnvalidateRecttoinvalidateo7izy
the client window; this program can therefore not rely upon the
WM ERASEBACKGROUND message for erasing the client window).

• READING THE MOUSE BUTTONS


The third important mouse parameter discussed in this chapter is
the state of the mouse buttons; that is, whether a given mouse button
ispressedorreleased.AmouseusedwiththePresentationManagercan
have either one, two, or three buttons. You can determine the number of
buttons available by calling the WinQuerysysvalue function (Figure
11.1), passing the identifier SV_CMOUSEBUTTONS, as follows:

LONG NumberButtons ,.

NumberButtons = WinQuerysysvalue
(HIND DESKTOP,
SV CM6USEBUTTONS ) ,.

Normally, when calling Presentation Manager functions or process-


ing messages, the buttons are numbered from left to right. Accordingly,
the button on the left is known as button number 1, the next button
to the right (if present) is known as button number 2, and the next but-
ton (if present) is known as button number 3. However, the user can
swap this ordering (using the Control Panel) so that the buttons are
numbered from right to left. The ordering of the buttons is not impor-
tanttotheprogram,unlessitissuesinstructionssuchas"Nowpressthe
left mouse button." The program can determine whether the button or-
dering has been swapped by calling WinQuerysysvalue, passing this
function the value SV SWAPBUTTON, as follows:
• 564 Programmer'sGuidetothe os/2Presentation
Manager

BOOL Buttonsswapped,.

Buttonsswapped = (BOOL)WinQuerysysvalue
(HIND DESKTOP,
sv swinBUTTONi ,.

(Note that your program can also scf the swapped state of the mouse
buttons by calling the Winsetsysvalue function.)
If your program uses more than one mouse button, you should pro-
videalternativecommandsthatcanbeissuedusingasinglebutton.For
example, in the program listed in Figure 11.21 (described later in this
section), the command issued by pressing mouse button 2 can also be
issued by pressing button 1 in conjunction with the Alt key.
Justasyoucanobtainthepositionofthemousepointereitherbycall-
ing a function or by processing a message, you can likewise determine
the status of the mouse buttons either by calling the WinGetKeystate
function or by processing the appropriate mouse messages.
The WinGetKeystate function (Figure 11.16) can be called to obtain
thestatusofavirtualkey(seetheexplanationofvirtualkeysinChapter
6) or a mouse button. You can pass this function a value identifying a
specific mouse button, and it will return a value less than 0 if the button
is pressed, or a value of 0 or greater if the button is released. A given
mouse button is specified by passing one of the following values:

VK BUTTONI
VK BUTTON2
VK BUTTON3
The following example determines whether mouse button 2 is pressed:

BOOL Button2Pressed,.

Button2Pressed = WinGetKeystate
(HEED DESKTOP,
VA BUETON2) < 0,.
Adding a Mouse Interface 565.

NotethatthebuttonstatusreturnedbyWinGetKeystateisthestatus
of the button at the time the last message obtained from the queue was
posted. This function is thus analogous to WinQueryMsgpos (which
obtains the pointer position at the time the last queue message was

WinGetKeystate
Purpose..
Determines whether a virtual key or mouse button is cur-
rentlypressedorreleased;alsoreturnsthetogglestatusofa
key.

Prototype..
SHORT APIENTRY WinGetKeystate
(Hue hwndDeskt°P, Fdheeny±a;utehFd¥kpo-pD::nKdTo°w? t°

SHORT vkey ) ,. i?]e)Tt:f:rnfe°:fttfev#oatfnegy c(:%ee=ab[e


identifying a mouse button:
vK BUTroNi
VK-BUTTON2
VK-BUTTON3

RetumValue..
If the specified key or mouse button is pressed, the high-
order bit of the word value returned by this function is set
(that is, the return value will be negative); otherwise, this bit
will be cleared. If the key is Joggled, the low-order bit of the
return value is set; a key is toggled if it has been pressed an
odd number of times since the system was started.

Notes:
The value returned by this function is the status of the key at
the time the last message obtained from the queue was
posted.

• Figure 11.16..
Tie WinGetKeystate Presentation Manager function
•566 Programmer's Guide to the OS/2 Presentation Manager

posted).ThereisnofunctionanalogoustoWinQuerypointerposforob-
taining the c#7`rc7if button state.
Thesystemalsoinformstheclientwindowofthestatusofthemouse
buttonsbysendingitanappropriatemessagewheneverabuttonisfirst
pressed or released. These messages are summarized in Table 11.2.
Whenever the user presses mouse button 1, the system sends the
WM_BUTTONIDOWN message; when this button is subsequently
released, the system sends WM_BUTTONIUP. The system sends
analogous messages for buttons 2 and 3. The action of pressing and
releasing a mouse button is termed a cJ€.ck. If the user clicks button 1
twice in rapid succession, with the mouse pointer in the same screen
area,thesystemsendsthefollowingsequenceofmessages:

WM_BUTTONIDOWN
WM BUTTONIUP
WM_BUTTONIDBLCLK
WM BUTTONIUP

Note that the message WM_BurTONIDBLCLK has replaced the


second WM_BUTTONIDOWN message to indicate that the two clicks

•__Table 11.2.. The Mouse Button Status M±ssages

Message ID Button Event


WM BUTTONIDOWN Button 1 has been pressed
WM BUTTONIUP Button 1 has been released
WM_BUTTON2DOWN Button 2 has been pressed
WM BUTTON2UP Button 2 has been released
WM BUTTON3DOWN Button 3 has been pressed
WM BUTTON3UP Button 3 has been released
WM BUTTONIDBLCLK Button 1 has been double-clicked
WM BUTTON2DBLCLK Button 2 has been double-clicked
WM BUTTON3DBLCLK Button 3 has been double-clicked
Adding a Mouse Interf ace 567.

qualify as a dot/Z7Je cJ1.ck. A double click consists of two clicks that oc-
cur within a certain short time span while the mouse pointer is con-
tained within a certain small screen area. The user can set the time span
through the Control Panel. Also, you can obtain or set the current
values for both the double-click time and the sensitive screen area by
calling WinQuerysysvalue or Winsetsysvalue (passing the constant
SV DBLCLKTIME for the time, SV_CXDBLCLK for the width of the
area, or SV_CYDBLCLK for the height of the area). The system sends
theanalogousmessageslistedinTablell.2forbuttons2and3.
Providingaspecialmessagefordouble-clickingexpandsthepossible
number of commands the user can issue with the mouse. The next sec-
tiondescribeshowthesecommandsaretypicauyusedbyanapplication.
Figures 11.17 through 11.21 provide an example program that
demonstrates how to design and install a custom mouse pointer, and
how to execute commands in response to mouse button activity. Figure
11.171ists a MAKE file for preparing the program; Figure 11.18 is the
linker definition file; Figure 11.19 is a resource script that defines
the mouse pointer; Figure 11.20 is a header file that is included in
Figuresll.19and11.21;andFigurell.21istheCsourcecode.
The custom mouse pointer used in this program was created in the
Icon Editor, as described in Chapter 10; it was then saved in the file

i Eii!:r3A±±.:Z|e prepares the program of Figure 11.21


#
FIGll Z!1.OEL : FIGll_21.C FIGll_20.H
€]L /W2 /c /Zp /G2ws FIGll_21.C

FIGll :L9.:RES : FIG1119.RC FIGll_20.H


Et= /r FIGll_19.5C

FIGll :21.EXE : FIG1121.OEL FIG1118.DEF FIG1119.RES


rink /NOD FIG11=21.OEL, , NULT OS2.LIB SL15CE.LIB, FIGll_18.DEF
rc FIG1119.RES FIGll_21.EXE

• Figure 11.17:
AjMAKiEfileforpreparingtheprogramofFigurell.21
•568 Programmer's Guide to the OS/2 Presentation Manager

FIGll_19.PTR. The pointer has the shape of a paintbrush, and it is used


for drawing lines within the client window. The pointer is defined in
the resource file of Figure 11.19 as follows:

POINTER ID POINTER "FIG1119.PTR"

; Figure 11.18

; Linker definition file for the program listed in Figure 11.21


NAME FIG1121
PROTMODE
HEAPSIZE 1024
STACKSIZE 8192
EXPORTS Wndproc

• Figure 11.18..
AlinkerdefinitionfitefortheprogramofFigurell.21

Figure 11.19

Resource script for the program of Figure 11.21

#include ''FIG1120.H"

POINTER ID_POINTER ''FIG1119.PTR"

• Figure ll.19..
A resource script for the progran of Figure 11.21

Figure 11.20

Header file included in the listings of Figures 11.19 and 11.21.

#def ine ID POINTER 1

• Figure 11.20..
AheaderfileincludedinthelistingsofFiguresll.19and11.21
Adding aMouselnterface 569 .

Figure 11.21

This program displays a custom mouse pointer, and responds to the mouse
buttons by drawing lines within the window.
*/

#def ine INCL_WIN


#include <OS2.H>
#include "FIGll_20.H"
#include <stdio.h>
#include <process.h> */
*/
::i: E:::r?::: i::::c:::;;age, , ,: ::=:n:::o:h:e::ag::g:::.program.
mESULT EXPENTRY Wndproc (HWND hwnd, USHORT msg, MPAEN mpl, MPARAI mp2) ;
*/
HAB HAncBlk; /* Anchor block handle. */
HWND HFrame; /* Frame window handle. */
HMQ HMesQue; /* Message queue handle

void main ()
(
HWND Hclient; /* Client window handle.
QMSG QueMess;
/* Message queue structure.
ULONG CtlData = /* Control windows to include:
FCF MINmx /* Minimize/maximize box.
FCF-SHELLPOSITION /* Make window visible on screen.
FCF-SIZEBORDER /* Wide sizing border.
FCF-SYSMENU /* System menu.
FCF-TASKLIST /* I)isplay program name in Task Manager.
FCF-TITLEBAR; /* Title bar.
*/
lIAncBlk = Winlnitialize /* Initialize the Presentation Manager. */
(0), /* Initialization options: must be 0.
*/
I"esQue = WincreateMsgQueue Create a message queue. */
(HAncBlk, Anchor block
All-J|\JL J--+ ,-,---handle.
_-____
0); Minimum queue size: 0 means default size.*/

WinRegisterclass /* Register a window class.


(RAncBlk, /* Anchor block handle.
''mlN„ , /* Window class name.
Wndproc, /* Window procedure associated with class.
CS SIZEREDRAW /* Invalidate entire window on size change
o)i /* Bytes of data storage for each window.
HFrame = Wincreatestdwindow /* Create a standard window collection.
(END DESKTOP, /* Parent window handle.
WS VISIBLE, /* Frame window style.
&cEIData , /* Address of control data.
''mlN„ , /* Client window class name.
'': Mouse Button Demo", /* Text for title bar.
OL' /* Client window style: none specified.
0' /* Resource module handle: none.

[#nue'xca#firogramthatdisp|aysacustommousepointerandrespondstothemousebuttons
• Figure 11.21..
•570 Programmer's Guide to the OS/2 Presentation Manager

0,
&Hclient) ;
/* Resource identification: none */
/* Address to receive client window hand. */
while (WinGetMsg
/* Get messages until WM_QUIT.
(HAncBlk, /* Anchor block handle.
&QueMess ,
0,
/* Address of message structure.
0,
/* Window filter: any window.
0))
/* First message identifier: n/a.
/* Last message identifier: n/a.
WinDispatchMsg (HAncBlk, &QueMess) ; /* Dispatch messages.

Quit (0); /* Exitprogramwith a 0 error level. */


} /* end main */

/*** The window procedure and subroutines. ***"******************************/


MRESULT EXPENTRY ButtonlDn
MRESULT EXPENTRY Button2Dn (HWND hwnd,
MRESULT EXPENTRY Create (HWND hwnd,
MRESULT EXPENTRY Destroy (HWND hwnd,
MRESULT EXPENTRY MouseMove (HWND hwnd,
(HWND hwnd,
static HPOINTER HMouseptr;
POINTL Savedpoint = {0,0}; /* Handle of the mouse pointer.
/* Saved value of last line endpoint.
MRESULT EXPENTRY Wndproc
(HWND hwnd, /* Window handle.
USHORT msg,
MPAFun mpl, /* The message.
MPAEN mp2) /* Message-specific information.
/* Message-specific information.
(
switch (msg)
(
/* Button I has been pressed.
case WM BUTTONIDOWN:
return ButtonlDn (hwnd,msg,mpl,mp2) ;

/* Button 2 has been pressed.


case WM BUTTON2DOWN:
return Button2Dn (hwnd,msg,mpl,mp2) ;
case WM CREATE:
return Create (hwnd,msg,mpl,mp2) ;
case WM DESTROY:
return Destroy (hwnd,msg,mpl,mp2) ;

/* Force the system to erase the client window.


case WM ERASEBACKGROUND:
return TRUE;

/* The mouse has moved within the client window.

• Figure 11.21..
Anexampleprogramthatdisplaysacustommousepointerandrespondstothemousebuttons(continued)
Adding a Mouse Interface 571.

case WM MOUSEMOVE:
return MouseMove (hwnd,msg,mpl,mp2) ;

default:
return WinDefwindowproc (hwnd,msg,mpl,mp2) ;
)

} /* end Wndproc */

MRESULT EXPENTRY ButtonlDn (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
HPS Hpresspace;
*/
/I. If hit key is pressed, send a WM_BUTTON2DOEN message.
if (WinGetKeystate
(HIND DESKTOP,
vK Ari) < 0)
(
WinsendMsg
( hwnd ,
WM BUTTON2DOWN,
mpl,
mp2) ,
return TRUE;
)

/.A Otherwise, draw a line from current point to mouse pointer position
H.presspace = WinGetps (hwnd) ; /,: 9P:a:`n, :``:::::n:::::Fr:P:::iL to
G]piMOve /* Set PM cu-rrent graphics point to
( Hpresspace , /* last endpoint.
&Savedpoint) ;
Savedpoint.x = MOUSEMSG(&msg) ->x; /* Adjust 'Savedpoint' to current
Savedpoint.y = MOUSEMSG(&msg) ->y; /* pointer position.
GpiLine /* Draw line from graphics point to
( Hpresspace , /* current mouse pointer position.
&Savedpoint) ;

WinReleaseps (Hpresspace) ; /* Release the presentation space.


return TRUE; /* Notify system that message has been processed.

} /* end ButtonlDn */

mESUI,T EXPENTRY Button2Dn (rmND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
/* Reset 'Savedpoint' to current mouse position.
Savedpoint.x = MOUSEMSG(&msg) ->x;
Savedpoint.y = MOUSEMSG(&msg)->y;

return TRUE;

} /* end Button2Dn */

• Figure ll.21..
[#nue`xca;mL#irogramthatdisp|aysacustommousepointerandrespondstothemousebuttons(Continued)
• 572 Programmer's Guide tothe os/2Presentation
Manager

mESULT EXPENTRY Create (HWND hwnd, USHORT msg, MPA:RAN mpl, MPARAM mp2)

* Quit program if mouse not installed.


f ( !WinQuerysysvalue
(END DESKTOP,
SV_MobsEPRESENT) )
ErrorQuit ("Program requires mouse") ;
/* Load custom pointer resource.
"ouseptr = WinLoadpointer
(HWND DESKTOP,
rmLL,
ID_POINTER) ;

if (HMouseptr == NULL)
ErrorQuit ("Cannot load pointer resource") ;
return FArsE ;
} /* end Create */

lmESULT EXPENTRY Destroy (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)
(
WinDestroypointer /* Release pointer handle.
("Ouseptr) ;
} /* end Destroy */

MRESULT EXPENTRY MouseMove (HWND hwnd, USHORT msg, MPZ~ mpl, MPZ~ mp2)
(
/* Set the mouse pointer to the custom pointer while the mouse is in the
client window. */
Winsetpointer
(HWND DESKTOP,
HMousEptr) ;
return TRUE;

} /* end MouseMove */

Void F::g=Q¥i:.~.~_` /: ::rminate program due to fatal error condition. */


(char *Message) /* Error mess-age-to displa} €5-I;e=: ---- `
char Buffer [60];
sprintf (Buffer,"Program Error: %s",Message) ;
W±nMe:§i:::§ESKTop, ;; ::::::y:: i;::::: :i:i:t:¥n¥::?°W.

• Figure ll.21..
An example program that displays a custom mouse pointer and responds to the mouse buttons (continued)
Adding a Mouse Interface 573.

Buffer, /* Message text.


''Pointer Demo" , /* caption.
0' /* Help window ID: not needed.
MB OK I /* Display an 'OK' button.
MB-ICONHAND) ; /* Display a hand icon.

Quit (1) , /* Call normal termination function.

} /* end ErrorQuit */

void Quit (int Errorcode)


(
WinDestroywindow (HFrame) ;
WinDestroyMsgQueue (HMesQue)
WinTerminate (HAncBlk) ;
exit (Errorcode) ;
) /* end Quit */

[X8nuerxea##irogramthatdisp|aysacustommousepointerandrespondstothemousebuttons(continued)
• Figure 1.1.21:

The constant ID_POINTER, defined in the header file of Figure 11.20, is


usedtoidentifythepointerresourcewhenitisloadedbytheCprogram
(Figure 11.21). The C program loads the pointer by calling WinLoad-
Pointer (Figure 10.8) during processing of the WM_CREATE message,
as follows:

IIMouseptr = WinLoadpointer
(HEED DESKTOP,
RILL ,
ID POINTER) ;

HMouseptr is defined as an external variable through the following


expression:

static HPOINTER HMouseptr,.

The pointer is released during processing of the WM_DESTROY


messageusingthefollowingcalltoWinDestroypointer:

WinDestroypointer
("ouseptr) ,.
• 574 Programmer's Guide to the os/2 Presentation
Manager

Theprogramcausesthesystemtodisplaythecustommousepointer
whilethepointerislocatedwithintheclientwindowbyissuingthefol-
lowing call to Winsetpointer each time the client window procedure
receives the WM_MOUSEMOVE message:

Winsetpointer
(HWND DESKTOP ,
ENous=Ptr) ,.

Note that the WM_MOUSEMOVE routine (the function MouseMove)


ignores the current pointer position; the WM_MOUSEMOVE message
is used simply as an indication that the pointer is currently located
somewhere within the client window.
The example program processes two mouse button messages: the
WM_BUTTONIDOWN message, sent when button 1 is pressed, and
the WM_BUTTON2DOWN message, sent when button 2 is pressed.
The WM_BUTTONIDOWN message is processed in the function But-
tonlDn, and the WM_BurTON2DOWN message is processed in But-
ton2Dn. In response to button 1, ButtonlDn draws a line from the
point saved in the variable Savedpoint to the current mouse position
(Savedpoint is a global POINTL structure that is initialized to the value
{0,0}). ButtonlDn also updates Savedpoint to contain the current
mouse position. Thus, the user can draw a sequence of connected line
segments as shown in Figure 11.24 (described later).
ThefunctionButtonlDndrawsalinesegmentbyperformingthefol-
lowing steps:

1. It calls winGetps (Figure 3.19) to obtain a handle to a presenta-


tion space.
2. It calls GpiMove (Figure 11.22) to set the c%rre#£ gr¢pfez.cs posz'f2.o#
maintained by the Presentation Manager to the value contained
in Savedpoint. This point will become the start of the line
Segment.
It calls GpiLine (Figure 11.23), which draws a line /rone the cur-
rent graphics point fo a specified point. The point specified by
ButtonlDn is the current mouse position. GpiLine thus draws a
line segment from the point that was stored in Savedpoint to the
current position of the mouse pointer. Note that the current
Adding a Mouse Interface 575.

pointerpositionaccompaniesallmousemessages,anditiseasily
extracted using the MOUSEMSG macro.
4. It calls winReleaseps (Figure 3.22) to release the presentation
Space.

GpiMOve
Purpose..
Sets the current graphics position.

Prototype..
BOOL APIENTRY GpiMove

::::N::S;pt i ) , =L:£;::;ti§a)a:je:St¥;T:[Lg:t:ie:±ir; (gdreaf;nheLgsLn


position.

ReturmValue..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
The current graphics position is initialized to the point (0,0)
when the presentation space is first obtained. GpiMove ex-
plicitlysetsthecurrentgraphicsposition;drawing functions
such as GpiLine also set this position (to the specified en-
ding point of the primitive that is drawn).

Relate d Functions ..
GpiLine (Figure 11.23)

• Figure 11.22..
Tire Gpt:Move Presentation Manager function
• 576 Programmer'sGuidetothe os/2Presentation
Manager

GpiLine
Purpose..
Draws a straight line from the current graphics position to
the specified endpoint, and resets the current graphics posi-
tion to this endpoint.

Prototype..
LONG APIENTRY GpiLine
(Eps hps , Handle to the presentation space in which
the line is to be drawn.
ppolNTL pptl) ,. Address ofa POINTL structure (defined in
Figure 3.28) containing the endpoint.

RetumValue..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
The beginning point of the line is the current graphics posi-
tion; since GpiLine resets the current graphics position to
the specified endpoint, you can draw a sequence of con-
nected line segments in a given presentation space by
repeatedly calling GpiLine, without explicitly setting the
current graphics position between calls. You can call Gpi-
Move, however, if you need to explicitly set the graphics
position.

Related Functions ..
GpiMove (Figure 11.22)

• Figure 11.23..
The GPILine Presentation Manager function
AddingaMouselnterface 577 .

Note that rather than accepting both a starting point and an ending
point, the function GpiLine receives only the ending point of the line.
The starting point of the line is the current graphics position that is
maintained by the Presentation Manager for a given presentation space.
When you first obtain a presentation space, the current graphics posi-
tion is initialized to the point (0,0). You can explicitly set it to an ar-
bitrary point by calling GpiMove; also, certain drawing functions, such
as GpiLine, reset the current position to the endpoint of the object
drawn. Thus, if the desired beginning point of the line is 71of the current
graphics position, you must call both GpiMove and GpiLine to fully
specify the line.
If, however, you are drawing a series of connected line segments
within a given presentation space, you need to call GpiMove only to set
the initial starting point. Since GpiLine automatically resets the current
point to the endpoint of the line drawn, you can draw each subsequent
connected line segment by simply calling GpiLine. (Even though the
linesegmentsdrawnbytheprogramofFigurell.21areconnected,But-
tonlDn must always call GpiMove, since it obtains a handle to a 71cw
presentation space each time it is called.)
In response to mouse button 2, the function Button2Dn resets Saved-
Pointtocontainthecunentmouseposition,usingthefouowingexpressious:

Savedpoint . x = MOUSEMSG (&msg) -> x,.


Savedpoint . y = MOUSEMSG (&msg) -> y,.

Pressingbutton2thusallowstheusertoresetthestartingpointinorder
to draw a new series of connected line segments.
The function Button2 receives control either when the user presses
mouse button 2 or when the user presses button 1 in combination with the
Altkey(whichisaprovisionforuserswithasinglemousebutton).When-
evertheuserpressesbutton1,thefunctionButtonlDnreceivesinitialcon-
trol; if, however, the Alt key is also pressed, ButtonlDn immediately
passes control to Button2Dn, through the following instructions:

if (WinGetKeystate
(HIND DESKTOP,
VA AIT) < 0)
(
WinsendMsg
• 578 Programmer's Guide tothe os/2Presentation
Manager

(hwnd,
" BUTTON2DOEN,
mpl,
mp2 ) '.
return TRUE,.
)

Note that the program of Figure 11.21 (like the program of Figure
11.14) erases the client window by returning TRUE from the
WM_ERASEBACKGROUND message. Accordingly, the client window
is cleared whenever the frame window is resized. Figure 11.24
illustrates the window and mouse pointer created by the program.

• CREATING A MOUSE INTERFACE


The previous sections have described the basic mouse operations:
determiningthepointerposition,settingthepointershape,andreading
the status of the mouse buttons. This section briefly describes how to
use these basic operations to create a standard mouse interface. The
guidelines described in this section are derived from the Presentation

• Figure ll.24..
The window created by the program of Figure 11.21
AddingaMouselnterface 579 .

Manager technical documentation and the W£.71dozos AppJ1.c¢££.o# Sfyzc


G#i.dc (see the Bibliography). As mentioned in Chapter 5, your applica-
tion will be easier for the user to learn and use if it conforms to the
standard interface.
In general, a Presentation Manager application should provide
mouse commands for all operations that can be easily and efficiently ac-
complished with the mouse. Note, however, that installing a mouse is
opf€.07i¢J; the user should be able to run Presentation Manager applica-
tions without a mouse (except for highly specialized programs that
would be impractical without a mouse). Therefore, you should provide
alternative keyboard commands for all mouse operations.
The following table defines the basic terms used to describe the ac-
tions that can be performed with a mouse:

Action D escription

Click Quickly pressing and releasing the mouse


button
Double-click Clicking the mouse twice in rapid succession,
while the mouse pointer remains in the same
screen area
Pressing the mouse button, and holding it
down while moving the mouse
Placing the pointer hot spot (for example, the
tip of the standard arrow pointer) on a specific
item or within a given area

Mouse Commands
This section lists the standard uses for mouse button 1. The use of
mouse button 2 is application-specific; note, however, that a program
should not depend upon the existence of more than a single button. Ac-
cordingly, a command issued through button 2 should be optional (a
command shortcut, for example), or you should implement an alterna-
tive keyboard command (possibly executed in combination with mouse
• 580 Programmer's Guide to the os/2PresentationManager

button 1). Mouse button 3,if present, is reserved for optional system
commands.
The following commands are recommended for marking selections
within text-based applications (see Chapter 9 for a discussion on text
selections and their relationship with the Presentation Manager clip-
board). Note that the recommended pointer for an area displaying text
is the I-beam (identified by the value SPTR_TEXT).

Mouse command Effect

Click Moves the text insertion point to the


position under the pointer
Double-click Selects the word under the pointer
Shift-click fxfc71ds the selection from the current
text insertion point or text selection
through the position under the pointer
Drag Selects text fro777 the position where the
button was pressed fo the position
where the button was released
Shift-drag fxfc7ids the selection from the current
insertion point or text selection
through the area selected by dragging
the mouse

Note that using the Shift key in conjunction with the mouse button in-
creases the number of commands that could be issued through the basic
mouse actions alone.
The following commands are recommended for selecting items from
lists (for example, selecting files from a list of file names). Note that the
standard arrow pointer (SPTR_ARROW) is recommended for selecting
list items.

Mouse Command Effect

Click Selects the item under the pointer (for


example, highlights a file name in a
list)
AddingaMouselnterface 581 .

Double-click Selects the item under the pointer and


performs the default action on that
item (for example, highlights a file
name ¢77d reads the file)

Shift-click £xfc#ds the selection from the pre-


viously selected item(s) to the item
under the pointer
Drag Selects all items extending fro77z the
position where the button was pressed
fo the position where the button was
released
Ctrl-click Selects a single discontinuous item
(that is, the previous selection remains
intact, and the newly selected item is
added to the selection without adding
intermediate items)
Ctrl-drag Selects a group of discontinuous items
(that is, the previous selection remains
intact, and the newly selected items
are added to the selection without ad-
ding intermediate items)
J pter twelve

Exploiting
Multitasking
and
Interprocess
Cornrnunication,
583.

.r
hapter 1 introduced the topic of multitasking and de-
scribed the three levels of multitasking supported by
OS/2: multiple screen groups, multiple programs, and
multiple threads of execution within a single program.
This chapter focuses on the finest of these three levels: multitasking of
threads. Specifically, it describes how to use multiple threads of execu-
tion within a Presentation Manager application.
AIl of the Presentation Manager programs described so far in this
book have consisted of a sl.71gzc thread. In these programs, when the
function main calls WinDispatchMsg to dispatch a message, control
does not return from WinDispatchMsg until the message has been
fully processed and the window procedure has issued a return state-
ment. Thus, messages are processed one at a time, and only one func-
tion within your program is active at a given time.
In general, using multiple threads of execution within a single ap-
plication is a useful device for increasing program efficiency and
throughput, and for simplifying complex program logic. Specifically,
under the Presentation Manager, starting multiple threads is an impor-
tant technique for performing lengthy tasks in response to keyboard or
mouse commands.
Since a program consisting of a single thread can process only one
message at a time, a message that initiates a lengthy operation (such as
recalculating a spreadsheet or printing a file) blocks the program from
processing further messages until the current operation is complete.
Thus, the program cannot respond to keyboard or mouse input while
the operation is in progress. Furthermore, the system does not allow the
user to switch to another application (using either the keyboard or
mouse) while the active application is processing a message (specifical-
ly, the system delays switching active applications until the window
procedure returns control and the main message-processing loop calls
WinGetMsg to obtain another message). Accordingly, the Presentation
Manager documentation recommends that the window procedure
return control within approximately 0.1 second.
If the program consists of a single thread, the window procedure ob-
viously cannot perform a lengthy operation and return control within
0.1 second. The best solution to this problem is for the window proce-
dure to start a second thread of execution to perform the lengthy opera-
tion, and then return control immediately. While the second thread is
• 584 Programmer's Guide to the os/2PresentationManager

running, the first thread can continue to process messages and the sys-
tern can allow the user to switch to another application.
This chapter describes how to start a new thread to perform a lengthy
operation from the window procedure. It then discusses methods for
synchronizing the activities of the two program threads using
semaphores and shared global variables. The chapter illustrates these
general techniques by describing the specific steps for implementing a
print routine within the Presentation Manager text editor presented in
the first part of the book. Printing a file is a good example of a lengthy
task performed in response to a keyboard or mouse message; also, run-
ning a printing routine as a secondary thread illustrates many of the
ways the activities of multiple threads must be synchronized.
This chapter presents only one of the ways that you can exploit multi-
tasking under the Presentation Manager. In addition to starting secondary
threads of execution, a Presentation Manager application can also run
other programs as child processes (for example, a text editor could run a
compiler as a child process, which would auow the user to continue edit-
ing while the compiler runs in the background). For further general infor-
mation on multitasking and inteaprocess communication under OS/2, see
the Progr¢77177ier's G%€.cZc fo OS/2 (cited in the Bibliography).

• USINGASECONDTHREAD
If the window procedure needs to perform a lengthy operation,
rather than simply calling the function that performs this operation as a
subroutine, it can call the OS/2 function DoscreateThread (Figure 12.1)
to execute the function as a second thread. The window procedure can
then immediately return control to the main message-processing loop;
while the second thread performs its task, the main thread resumes nor-
mal message processing. Figure 12.2 illustrates the difference between
executing a lengthy routine as a subroutine (part A) and running it as a
separate thread (part 8); as you can see in this illustration, the important
benefit of starting a new thread is that it significantly shortens the mes-
sage-processing loop.
Exploiting Multitasking and Interprocess Communication 585.

DoscreateThread
Purpose..
Starts a new thread of execution within the current process.

Prototype..
USHORT APIENTRY DoscreateThread
(volD FJm *pfnFunction (VolD) , Address of thread entry
point.
PTID ptidThread Pointer to variable to
receive the thread
identifier.
PBYTE pbThrdstack) ,. Pointer to the top of the
thread's stack.

Return Value ..
Zero if the function was successful; if an error occurred, the
function returns one of the following nonzero values:

ERROR NO PROC SLOTS


ERROR NOT ENOUGH_MEMORY

• Figure 12.1..
Tree DoscreaLte:ThreaLd OS /2 f unction

Starting the Thread


To illustrate the techniques for using an additional thread of ex-
ecution,considertheroutinethatprocessesthePrintmenucommandin
the text editor presented as the example application in the first part of
the book. When the user selects the Print command from the File sub-
menu, the client window receives a WM_COMMAND message with a
command code of ID PRINT. In the final version of the program listed
inFigure8.38,theroutinethatprocessesthismessagesimplydisplaysa
message box informing the user that the command has not been imple-
mented, and immediately returns.
Lil-
• 586 Programmer's Guide to the os/2 Presentation Manager

• Figure 12.2..
Using a single thread vs. using two threads to process messages
Exploiting Multitasking and Interprocesscommunication 587 .

The purpose of the Print command is to send the current contents of


the file buffer to the printer. Since this process typically requires much
more than 0.1 second, the routine that performs the actual printing
should be executed as a separate thread. The code that starts this thread
is listed in Figure 12.3; to implement the Print command, you should
place this code within the function Command (of Figure 8.38), under
the WM PRINT case.

case ID PRINT: /* 'Print' item of 'File' submenu.

/* Determine if print routine is already -active.


____I _I ----- L---
Result = Dossemwait /* Test status of print semaphore.
( &Sem , /* RAM semaphore handle.
OL); /* Timeout: return immediately.
if (Result) /* Print routine already active.
( /* Warn user and return.
WinMessageBox
(END DESKTOP,
HFrame ,
"Print Routine Already in Progress",
''PM Text Editor",
0,
MB OK I
MB-ICONASTERISK) ;
return FALSE ;
)

/* Set semaphore to restrict buffer from main thread.


Dos5Semset (&Sem) ;

/* Spin off separate thread to print file.


Re,su|!:::§§§§:::::Thread;::::::::s::h:::::=:::::::n

+ sizeof (Printstack) ) ;
if (Result) /* 'DoscreateThread' failed.
Wir"essageBox
(END DESKTOP,
hwnd ,
''Cannot start print thread.",
''PM Text Editor",
0,
HB ICONASTERISK I
MB=OK) ,

return FALSE ;

• Figure l'L'..3..
The routine for processing the Print menu command
• 588 Programmer's Guide to the os/2 Presentation
Manager

The significant portion of this code for the present discussion is the
following call to DoscreateThread (most of the other instructions
manage the semaphore, and will be described later in the chapter):

USHORT Result,.

Result = DoscreateThread
(PrintThread,
&IDThread,
Printstack
+ sizeof (Printstack)) ,.

The first parameter supplies the address of the function that the new
thread is to begin executing. This function is declared as follows:

VOID FAR PrintThread (VOID) ,.

You should use this format when declaring any function that is to be ex-
ecuted as a new thread. Note that there are no parameters; the system
does not pass parameters to the function that receives initial control
when a new thread is started. The function PrintThread will be
described later in the chapter.
The second parameter to DoscreateThread supplies the address of
the variable that is to receive the identifier of the new thread. All threads
running under OS/2 are given unique identifiers (which must be sup-
plied to functions such as DosSuspendThread). The example routine
ignores the thread identifier.
The final parameter contains the address of the fop of the thread's
stack. (The top of the stack is the byte immediately following the
memory block that is reserved for the stack; note that the stack grows
dow# in memory, and the stack pointer is decremented by 2 bc/ore the
first word pushed on the stack is written to memory.) Each thread owns
its own stack; when your program starts a new thread, it is responsible
for reserving the memory for the new thread's stack. The required stack
size depends upon the specific function. A recommended minimum
sizeis512bytes;however,ifthefunctioncallsanyOS/2services(orany
other dynamic-link functions), the recommended minimum is 2048
Exploiting Multitasking and Interprocess Communication 589.

bytes plus the requirements of the function itself . A generous stack size
for the function PrintThread (which, as you will see, calls OS/2 func-
tions) is 4096 bytes; this stack is declared as follows:

BYTE Printstack [4096] ,.

Note that Printstack is declared outside the scope of any function


(that is, it is an external array), so that it will be permanently reserved
within the program's data segment. You must not define the stack as a
local variable within a function that may terminate while the thread is
still running, since the storage for local data is relinquished upon the
function's exit (unless it is declared as static data). Specifically, the stack
must not be defined as local data within the function Command (which
calls DoscreateThread), since this function typically terminates while
the secondary thread is still running.
In general, it is possible to execute the s¢77ie function by more than
one thread at a given time (the second thread is said to create a new {.71-
sf¢7icc of the function it executes). For example, if a program issues a
second identical call to DoscreateThread while the thread executing
thespecifiedfunctionisstillactive,thesystemwillsimplystartanother
new thread executing the same body of code. In this case, you must al-
locate a 7ieco stack for each new thread; you can allocate multiple stacks
dynamically by calling the OS/2 function DosAllocseg (Figure 9.1).
Note that the example program discussed in this chapter needs to
define only a single stack, because, as you will see later in the chapter, a
semaphore prevents the program from calling DoscreateThread when
the print routine is already active.
Although each thread owns its own stack, it shares all other objects
belonging to the program, such as memory segments and open file
handles. Accordingly, all threads can directly access externally declared
program data (that is, data declared outside the scope of a function).
Also, separate threads can share all Presentation Manager objects other
than message queues, such as windows, dialog boxes, presentation
spaces, and resources.
The DoscreateThread function returns immediately after beginning
the new thread. If an error occurred, this function returns a nonzero
error code; in this case, the example code in Figure 12.3 displays a mes-
sage box informing the user of the error, and returns.
• 590 Programmer'sGuidetothe os/2Presentation
Manager

Writing a Function for a New Thread


This section discusses the guidelines for writing a function that is
to be executed as a new program thread. An example of such a function
is PrintThread, which prints the contents of the file buffer; this function
islistedinFigure12.4.Ifyouareimplementingaprintcommandforthe
text editor of Figure 8.38, you should place PrintThread within the buff-
er-management module, since it directly accesses the data structures
belonging to this module.
The function PrintThread has the following basic structure:

VOID FAR PrintThread (VOID)


(

DosExit (EXIT THREAD,0) ,.


)

Note that although you cannot pass parameters to a function executed


as a new thread, this function can call additional functions, passing any
required parameters. Also, as you will see in the next section, there are
many alternative.ways for the main thread to pass information to the
new thread. The OS/2 function DosExit (Figure 12.5) terminates
the thread; the value EXIT_THREAD, passed as the first parameter,
causes DosExit to terminate only the current thread rather than the en-
tire application. The second parameter is an exit code, which the main
thread can retrieve, if desired, by calling the OS/2 function Doscwait.
A function executing a new thread can freely call the Dos OS/2 ser-
vices, since these functions have been designed to execute properly
within a multitasking environment. PrintThread uses the standard
OS/2 functions Dosopen, Doswrite, and Dosclose to open the printer
device, to write each file line to the printer, and to close the printer. (The
other tasks performed by this function are explained in the next section.)
A function executed as a separate thread, however, is 71of automat-
ically free to call any Presentation Manager function. Remember that
the message queue created by the main thread (by calling Wincreate-
MsgQueue) belongs only to the main thread; it cannot be shared by
another thread. A second thread, therefore, does not have a message
Exploiting Multitasking and Interprocess Communication 591.

VOID FAR PrintThread (VOID)


/* Note: This routine prints the current contents of the file buffer. It
rulis as a separate thread that is concurrent with the main application
thr eald .
*/
(
register int i; /* Loop counter.
HFILE Hprinter; /* Handle to printer.
Usli:ORT Byteswritten /* Receives number of bytes printed.
Usli[ORT Action; /* Receives action taken by 'Dosopen' .
Dosopen /* Open the printer.
( „ PRN„ ' /* Printer file name.
&Hprinter' /* Receives printer handle.
&Action, /* Receives action taken: n/a.
OL' /* New file size: n/a.
0, /* File attribute: n/a.
1, /* Open flags: open if file exists.
Ox41, /* Open mode: share/write only.
OL); /* Reserved: must be 0.

/* PLr-int all lines in the file buffer.


for (i = 0; i <= LastLine; ++i)
* Test flag for aborting print routine.
f (Abortprint)
break;

/* Write a single line.


Doswrite
(Hprinter, /* File handle.
LineTable [i].LineAddress, /* Address of source buffer.
LineTable [i] .LineLength-1 /* Number of bytes to print.
&Byteswritten) ; /* Receives nun. bytes written

/* Write terminating carriage-return character.


Doswrite
(Hprinter, /* File handle.
„\r„ , /* Address of source buffer.
1, /* Number of bytes to print.
&Byteswritten) /* Receives nun. bytes written
)

/* Close the printer.


Dosclose (Hprinter) ;

/* Clear the semaphore to restore access to file buffer to main thread. */


Dossemclear (&Sem) ;

/* Terminate the print thread.


DosExit (EXIT THREAD,0) ;

} /* end PrintThread */

• Figure l',7..4..
The /7mci!z.07t PrintThread
• 592 Programmer'sGuide to the OS/2 Presentation Manager

DosExit
Purpose..
Terminates either a single thread or an entire process.

Prototype..
VOID APIENTRY DosExit
(USHORT fTerminate, Terminate flag; if assigned
EXIT_THREAD, only the current
thread is terminated; if assigned
EXIT_PROCESS, all threads in the
application are terminated.
USHORT usExitcode) ,. The thread or process exitcode.

Return Value ..
This function does not return.

• Figure 12.5..
The DosExft OS|2 f unction

queue unless it explicitly calls WincreateMsgQueue to create its own.


If a new thread does not own a message queue (such as the thread that
executes PrintThread in the example), it cannot call a Presentation
Manager function that creates a window (such as WincreateMsg-
Queue) or sends a message (such as WinsendMsg); nor can it call a
Presentation Manager function that indirectly causes a message to be
sent (such as WinsetFocus). See the Presentation Manager documenta-
tion for a current list of the functions that may not be called from a
queueless thread.
Note that if a new thread creates a message queue and a window, it
can send and receive Presentation Manager messages; messages are one
of the forms of communication among separate threads discussed in the
next section.
Standard C library functions are also off-limits for a new thread.
There are two problems with these functions. First, a standard C library
Exploiting Multitasking and Interprocess Communication 593.

functiongenerallyincludesastack-checkingroutineatthebeginningof
thecode.Thisroutineexpectsthefunctionstacktobelocatedinthenor-
mal stack area of the automatic data segment; as you have seen, how-
ever, the stack for a new thread is typically located either in the
program's data area or in a separate segment dynamically allocated
through the DosAllocseg function. Accordingly, the stack-checking
routine will abort the program. Remember that stack checking for any
function that you write is turned off through the /Gs option normally
usedwhencompilingaPresentationManagerapplication(thisflagwas
described in Chapter 2).
ThesecondproblemwithstandardClibraryfunctionsisthatmostof
them can be called by only one thread at a given time (such functions
are termed 71o7irce7if7'¢71f). Therefore, if the code executed by the main
thread contains calls to a library function such as sprintf, a function ex-
ecutedbyasecondthreadmustnotcallthisfunction,sinceboththreads
may attempt to execute the function at the same time.
Because of these problems, the example program uses OS/2 Dos
functions rather than C library functions for printing the file. Note,
however, that Microsoft C version 5.1 now supplies a special set of
library functions that can be executed simultaneously by .multiple
threads.Seethecompilerdocumentationforinformationonusingthese
functions.
The previous section discussed the possibility of starting two concur-
rent threads that execute the same body of code (by making a second
identical call to DoscreateThread before the thread started by the first
call has terminated). If your program can perform such an action (the
example program cannot), not only must you reserve a separate stack
for each thread, but you must also appropriately declare all variables
usedbythesethreads.Youshoulddeclarevariablesthataretobesfe¢7`cd
by all instances of a function as external data or as static data declared
within the scope of the function. You should declare variables that are
to be prz.zMfc for each instance as automatic data (data declared within
the function that are not static; these data are located within the stack,
which is distinct for each thread).
• 594 Programmer's Guide to the os/2Presentation
Manager

COMMUNICATING
• BETWEENTHREADS
In general, when two or more threads use or manipulate the same
program object, the threads must synchronize their activities to prevent
conflicts. For example, two threads should not attempt to update the
same section of a file at the same time; nor should they simultaneously
try to read and increment a program counter. Also, separate threads
commonly need to communicate while sharing a common task. For ex-
ample, one thread may fill a buffer with data, while another thread
processes these data; the first thread may have to notify the second
thread when the buffer contains valid data.
Implementing the print routine described in this chapter requires
communication between the two program threads to achieve the fol-
lowing four purposes:

• The program must prevent modification of the file buffer while


the buffer is being printed.
• The program must not start another print routine thread while a
print thread is already active.
• The program must not free the presentation Manager heap while
it is being accessed by the print routine.
• The main thread must be able to signal the print routine to abort.

The first three purposes are achieved using an OS/2 semaphore, and
the last is accomplished with a global program variable. This section
discusses using semaphores and global variables within the context of
the example program. It then describes the use of messages as a form
of communication between separate program threads.

Using Semaphores
and Global Variables
A semaphore is a program flag used to communicate simple
``stop" and ``go" information between separate threads or processes. A
semaphore can be in one of two states: cJc¢r, generally indicating that a
Exploiting Multitasking and Interprocess Communication 595.

threadshouldproceed,andsef,indicatingthatathreadshouldstopand
possibly wait for some event. OS/2 provides a large collection of func-
tions for creating and managing semaphores; this section discusses
three of these functions: Dossemset, Dossemclear, and Dossemwait.
Rather than providing a general explanation of the use of semaphores,
this section describes specifically how semaphores are used to imple-
ment the print routine within the example program.
First, the example program creates a semaphore by making the fol-
lowing external declaration at the beginning of the code (outside the
scope of a function):

UI.ONG Sem = 0,.

Such a semaphore, declared within your program, is known as a RAM


semaphore (OS/2 also provides sysfeffl semaphores, which are created
and stored intemally by the system and are more easily shared among
separate processes). Note that the semaphore is assigned a value of 0,
which places it initially in the clear state.
Whenever the user selects the Print command, the print routine
(the ID PRINT case of the function Command,listed in Figure 12.3)
sefs the semaphore Sem immediately before starting the thread that
prints the file. The semaphore is set through the following call to Dos-
Semset (Figure 12.6):

Dossemset (&Sem) ,.

The parameter passed to Dossemset is the handle of the semaphore,


whichforaRAMsemaphoreissimplythefaraddressofthesemaphore
(note that the compiler automatically converts the near address &Sem
to a far address, since this parameter is declared as a far pointer).
Immediately before the print thread terminates, the function Print-
Thread (listed in Figure 12.4) cJc¢rs the semaphore by calling Dossem-
Clear (Figure 12.7), as follows:

Dossemclear (&Sem) ,.

Since these two function calls are the only points in the example pro-
gram where the semaphore is either set or cleared, the semaphore is in
thesetstateonlywhiletheprintroutineisactive.Accordingly,theother
• 596 Programmer'sGuide tothe os/2Presentation
Manager

Dossemset
Purpose..
Sets the specified semaphore.

Prototype..
USHORT APIENTRY Dossemset
(HSEM hsem) ,. Semaphore handle; for a RAM semaphore,
this parameter should be the far address of
the semaphore; for a system semaphore, the
parameter should be the handle returned by
Doscreatesem or Dosopensem.

Return Value ..
Zero if the function was successful, or one of the following
nonzero error codes if an error occurred:

ERROR_EXCL_SEM ALREADY OWNED


ERROR INVALID IIANDLE
ERROR_TOO_MANY_SEM_REQUESTS

Related Functions ..
Dossemclear (Figure 12.7)
Dossemwait (Figure 12.8)

• Figure 12.6..
The Dosserr[Set os/2 function

partsofthecodecantestthissemaphoretodeterminewhethertheprint
routine is currently executing. The program tests the semaphore in
three different situations.
First, before the program issues any instructions that modify the file
buffer, it tests the state of the semaphore. If the semaphore is set, the
modificationisnotperformed.(Attemptingtomodifythefilebufferwhile
its contents are being printed could result in printing erroneous data.) The
Exploiting Multitasking and Interprocess Communication 597 .

Dossemclear
Puxpose..
Clears the specified semaphore.

Prototype..
USHORT APIENTRY Dossemclear
(HSEM hsem) J. :f#a°ieeFearnsdh]:iferbaeife¥=eamdad¥:s°sr:'f
the semaphore; for a system semaphore, the
parametershouldbethehandlereturnedby
Doscreatesem or Dosopensem.

RetumValue..
Zero if the function was successful, or one of the following
nonzero error codes if an error occurred:

ERROR EXCL SEM_ALREADY_OWNED


ERROR INVALID_HANDLE

Related Functions ..
Dossemset (Figure 12.6)
Dossemwait (Figure 12.8)

• Figure 12.7..
Tfie Dosse"Clea;I OS/2 function

semaphore is tested at these points in the code by calling the function


Dossemwait (Figure 12.8), as follows:

USHORT Result ,.

Result = Dossemwait
(&Sem,
OL) ,.
• 598 Programmer's Guide to the os/2Presentation
Manager

Dossemwait
Purpose..
Waits, if necessary, for the specified semaphore to be cleared,
or until the given timeout has elapsed.

Prototype..
USHORT APIENTRY Dossemwait
(HSEM hsem, Semaphore handle; for a RAM semaphore,
this parameter should be the far address of
the semaphore; for a system semaphore, the
parameter should be the handle returned by
Doscreatesem or Dosopensem.
LONG ITimeout) ,. Specifies the maximum time to wait for the
semaphore to clear; if this parameter is 0, the
function returns immediately, returning 0 if
the semaphore was clear or the nonzero
value ERROR SEM TIMEOUT if the
semaphorew;sset;ifthisparameterisgiven
the value -1, the function waits indefinitely
for the semaphore to clear.

Return Value ..
Zero if the semaphore was cleared; ERROR SEM TIMEOUT
if the semaphore was not cleared by the time tie specified
timeout expired; or one of the following nonzero error codes
if an error occurred:

ERROR_EXCL_SEM ALREADY OWNED


ERROR INTERRUPT
ERROR INVALID rlANDLE

RelatedFunctions..
Dossemclear (Figure 12.7)
Dossemset (Figure 12.6)

• Figure 12.8..
The DossemwaLft OS/2 f unction
Exploiting Multitasking and Interprocess Communication 599 .

The first parameter to Dossemwait is the semaphore handle, as ex-


plainedpreviously.Thesecondparameteristhefz.777co%fflag;sincethis
parameter is assigned 0, Dossemwait will not wait. Rather, it returps
immediately,passingbackavalueindicatingwhetherthesemaphoreis
set or clear. A zero return value indicates that the semaphore is clear,
and a norraero value indicates that it is set (or that an error occured; the
examplesinthischapter,however,donottestforerrorcodesandsimp-
ly assume that a nonzero return code indicates that the semaphore is
set). Such tests for the state of the semaphore are placed at the beg£.71-
#1.71gs of the following functions or routines:

1. The function character, which processes keystrokes that have


character codes.
2. The vK DELETE and vK_F9 routines within the function virt-
Key,whichprocesstheDelkeyandtheF9key.
3. :chuet:?thpeAf:s:er:::nmea#hoFtiheeEf:i:C±::ucb°ym±=s:::;;t±:hcL:;:
board data into the file.
4. The routine that processes the New file command in the
ID NEW case of the function Command.
5. The routine that processes the open file command in the
ID OPEN case of the function Command.

Ifthesemaphoreisset,routines1and2wamtheuserbysoundingthe
speaker,andretumwithoutperformingthefflemodification,asfollows:

if (Result)
(
Wirnlarm (HIPND DESKTOP, WA_ERROR) ,.
return TRUE,.
)

Routines 3, 4, and 5 warn the user by displaying a message box,


and then return without performing the requested operation. For
• 600 Programmer's Guide to the os/2Presentation
Manager

example,thepasteroutinecontainsthefollowingstatementsimmedi-
ately after the call to Dossemwait:

if (Result)
(
WirMessageBox
(HEED DESKTOP,
HFrame,
"Cannot Paste into File\n''
``Print Routine in Progress'',
"PM Text Editor'',
0'
ue OK I
MB ICONASTERISK) ,.

return FALSE,.
)

Thesecondprimaryuseforthesemaphoreistopreventtheprogram
from starting a second instance of the print function, PrintThread,
whilethisfunctionisalreadyactive.Accordingly,theID_PRINTroutine
listed in Figure 12.3 issues the following statements bc/ore calling Dos-
CreateThread to start the new thread:

Result = Dossemwait
(&Sem,
OL) ,.
if (Result)
(
WirMessageBox
(Hue DESKTOp,
HFrane,
``Print Routine Already in Progress'',
"PM Text Editor'',
0,
RE OK I
MB ICONASTERISK) ,.
return FALSE,.
)
Exploiting Multitasking and Interprocess Communication 601 .

The third and final use for the semaphore within the example pro-
gram is to prevent the user from terminating the program while the
print thread is still active. Terminating the program while the print
thread is active not only would interrupt the print job, but also would
probably result in a protection fault. Remember that the termination
routine (the function Quit) first calls WinDestroyHeap to release the
heap memory; if the print thread subsequently attempts to access this
memory, the system immediately ternrinates the program with a
protection fault message.
Topreventaprogramexitwhiletheprintthreadisstillactive,theex-
ample program provides a function (Close, listed in Figure 12.9) to

mESULT EXPENTRY Close (HWND hwnd, USHORT msg, MPARAM mpl, MPARAM mp2)

§§EBE: ::::¥t ; ,: R:::::s:o::o¥r::s::::e::Sit.


/* Determine if print routine is busy.

::s::i:i:::ssemwalt ;: Tit::i¥::i:i¥j;;diately.
£eply = Wi"essageBox /* Query user whether to abort print.
(END DESKTOP,
hund ,
''Print Routine in Progress\nAbort Print?" ,
''PM Text Editor",
0,
MB YESN0 I

if (R¥:I;C:¥Q#:::i?¥!; /* user wants to abort.


(
Abortprint = TRUE; /* Set global flag to stop print routine. */
/* Wait until print thread clears the semaphore before ending.*/
Dossemwait
( &Sem , /* RAM semaphore handle.
-1L) ; /* Timeout: don't return until clear.
)
else
return FALSE;
)
WinpostMsg /* End program by posting WM_QUIT message.
( hwnd , /* Recipient window: client.
" QUIT, /* Message ID.
OL' /* TxpL.. n/a.
OL); /* "pp... n/a.

) /* end Close */

• Figure.12®9..
Tfie function Close of the example program
®602 Programmer's Guide to the OS/2 Presentation Manager

process the WM_CLOSE message (Figure 12.10). The WM CLOSE mes-


sage is sent to the client window when the user selects the Close item
fromthesystemmenuordouble-clicksthemouseonthesystemmenu
icon. Processing this message allows your program to perform any re-
quiredfinaltasksbeforethewindowisdestroyedandtheapplicationis
terminated; this message also gives your program the opportunity to
prezJc7if ending the program.
If you pass the WM_CLOSE message to the system for default
processing (by calling WinDefwindowproc), the system causes the
programtoterminatebyposting(thatis,placinginthemessagequeue)
the WM_QUIT message (Figure 2.10). If your program processes this

WM_CLOSE
Purpose..
This message is sent by the system to the client window
when the user selects the Close item from the system menu
or double-clicks the mouse on the system menu icon.

Parameters..
REARAM mpl NULL.
REARAM mp2 NULL.

Return Value ..
NULL.

Notes..
Thedefaultprocessingforthismessage(performedbyWin-
Defwindowproc) is to terminate the application by posting
the WM_QUIT message to the window's message queue. If
your application processes this message, it can post
WM_QUIT or call WinDefwindowproc to terminate the
program, or simply return NULL to prevent terrfunating
the program.

• Figure 12.10..
The WM_CLOSE Presentation Manager function
Exploiting Multitasking and Interprocess Communication
603.

message, however, you can either post the WM_QUIT message to ter-
minate the program, or simply issue a return statement to allow the
program to continue.
InresponsetotheWM_CLOSEmessage,thefunctionClosefirsttests
the semaphore, as explained above, to determine whether the print
thread is active. If the thread is 7iof active, the function proceeds to ter-
minatetheprogrambypostingtheWM_QUITmessage.Themessageis
postedbycallingtheWinpostMsgfunction(Figure12.11),asfollows:

WinpostMsg
(hund, /* Recipient window: client.
" QUIT, /* Message ID.
OL,
* XPL.. nla.
OL) ,.
* Txp2... n/a.

Note that WinpostMsg, in contrast to WinsendMsg, places the mes-


sageinthetargetwindow'smessagequeueratherthandirectlyinvok-
ing the window procedure. As described in Figure 2.10 and explained
in Chapter 2, the WM_QUIT message causes WinGetMsg to return a
value of FALSE, which terminates the main message loop and ends the
Program.
If the print thread is currently active, the Close function displays a
message box asking the user whether the print job should be ter-
minated. If the user chooses 7iof to terminate, Close simply issues a
return statement, which causes normal processing to resume (7io
WM_QUIT message is posted).
If, however, the user decides to abort the print routine and end the
program, Close first sets the global flag Abortprint to TRUE. As you
canseeinFigure12.4,thePrintThreadfunctionteststhisflagwitheach
passoftheloopthatprintsthelinesofthefile;ifitfindsthatAbortprint
is TRUE, it immediately exits from the printing loop, closes the printer,
clears the semaphore, and terminates the thread. Abortprint is an ex-
ample of a shared memory location used to communicate information
between threads. External memory variables can be easily shared
among threads, since all program threads have equal access to the
memory segments owned by the process in which they run. (As men-
tioned in Chapter 1, OS/2 also provides functions that allow separate
processes to share memory segments; shared memory is an important
form of interprocess communication.)
• 604 Programmer's Guide to the os/2 Presentation
Manager

WinpostMsg
Purpose..
Posts a message to the message queue belonging to the
specified window.

Prototype..
BOOL APIENTRY WinpostMsg
(HWND hwnd, Handle of the target window.
USHORT msg, The identifier of the message that is being
sent.
REARAM mpl , The first message parameter; the meaning is
specific to the message.
REARAM mp2 ) ,. The second message parameter; the meaning
is specific to the message.

RetumValue..
TRUE if the function was successful, or FALSE if an error
occurred.

Notes..
WinpostMsg places the message in the target window's
message queue and returns immediately (in contrast, Win-
SendMsg calls the target window procedure directly, and
does not return until this procedure has terminated). Accord-
ingly, WinpostMsg does not return the result of the message
processing, but only an error code indicating whether the
message was successfully posted to the queue.

RelatedFunctions..
WinsendMsg (Figure 4.8)

• Figure 1211..
The WinpostMs8 Presentation Manager function
Exploiting Multitasking and Interprocess Communication
605.

After Close has set Abortprint to TRUE to end the print routine, it
does 7iof directly proceed to terminate the application. Rather, it first
waits until PrintThread has successfully ended (it cannot assume that
PrintThread ends immediately). To make sure that PrintThread has
ended, it again calls Dossemwait, this time passing a timeout value of
-1L, which causes Dossemwait not to return until the semaphore has
been cleared. The call to Dossemwait is as follows:

DO_;:S:;in:,aLt ;: =me::=P::::th:::::i until clear. :;

Note,therefore,thatDossemwaitcanbeusednotonlytotestthevalue
of a semaphore, but also to cause the program to pause until the
semaphore is clear. Also, if you set the timeout parameter to a value
greaterthan0,thefunctionwillwaituntileitherthesemaphorehasbe-
come clear or the specified timeout period has elapsed.
You should make one final change in the text editor program to im-
plementtheprintroutine.Notethattheusercanalsoterminatethepro-
gram by selecting the Exit item from the File submenu, as well as
through the Close item of the system menu. The routine that handles
theExitcommandinthepriorversionoftheexampleprogram(listedin
Figure 8.38, in the ID_EXIT case of the function Command) directly
calls the Quit function, which immediately aborts the program. Since
this tactic would bypass the test for an active print thread, the routine
should instead pass control to the code that handles the WM_CLOSE
message, as follows:

case ID EXIT:

WinsendMsg
(hwnd,
" CLOSE,
OL,
OL) ,.

return FALSE,.
•606 Programmer's Guide to the OS/2 Presentation Manager

Using Messages
Semaphores and shared memory are traditional forms of inter-
process communication available to all OS/2 protected mode
programs. Presentation Manager programs can also use messages as a
form of communication among separate threads. To be able to send and
receive messages, each thread must create at least one window; the
threads can then exchange messages using the standard Presentation
ManagerfunctionsWinsendMsgandWinpostMsg.Notethatmessage
identifiers are not limited to the predefined messages that have been
described in this book, but can also be programmer-defined messages
thatarerecognizedonlybythethreadsinvolvedintheexchange.
Thefollowingarethespecificstepsyoucanusetoestablishmessage
communication between the main program thread and a new thread
begun by calling DoscreateThread:

1. The new thread should call wincreateMsgQueue (Figure 2.3) to


create a message queue. Note that the new thread does 7iof have
to call Winlnitialize; rather, it can pass the anchor block handle
obtainedbythemainthread(Winlnitializeneedbecalledonly
once by a given process).
2. The new thread should then call winRegisterclass (Figure 2.4)
toregisterawindowclass,passingthenameofthewindowpro-
cedurethatwillprocessthemessagessenttothewindowbelong-
ing to the window it creates.
3. The new thread can call the presentation Manager function win-
Createwindow (Figure 12.12) to create an oZ7/.ccf ztJ2.72dozt7. An ob-
ject window is one that is not displayed on the screen, does not
receive input messages, and has no parent; an object window,
however, can serve as a vehicle for receiving messages from
other windows. To create an object window, you should pass
Wincreatewindow the identifier HWND_OBJECT as the handle
of the parent window (the first parameter), and the address of
thewindowprocedureasthesecondparameter.Theremaining
parameters should all be 0.
Exploiting Multitasking and Interprocess Communication 607 .

Since the newly created window is an object window, it does not


have to process WM_PAINT or other system messages (any sys-
temmessagesitreceivescansimplybepassedtotheWinDef-
Windowproc function for default processing). Rather, it can
focus on processing the programmer-defined messages sent by
other windows.

Note that the identifiers for programmer-defined messages should


have values equal to or larger than the value WM_USER. For example,
youcoulddefineasetofprogrammer-definedmessagesasfollows:

#define WM PRIVATE 00
#define "-PRIVATE=01
#define WM PRIVATE 02

Note that using messages as a form of private communication be-


tween program threads represents the third major use for Presentation
Manager messages discussed in this book. To summarize, the book has
discussed the following three purposes served by the Presentation
Manager message mechanism:

• Messages are the primary channel through which the program


receives input and is informed of significant events.
• By sending messages to system window procedures, the applica-
tion can control these windows and receive important system
services. The predefined messages described in this book thus
form a significant extension to the application program interface
accessed through the system functions (W£.71, Gp£., Dos, and
others).
Messages can serve as a private channel of communication be-
tween separate program threads.
• 608 Programmer's Guidetothe os/2Presentation
Manager

Wincreatewindow
Purpose..
Creates a new window.

Prototype..
HWND APIENTRY Wincreatewindow
(Hum hwndparent, The handle of the parent
window; the value
HWND DESKTOP indicates
the desktop window and
creates a top-level window; the
value HWND_OBJECT creates
an object window (which has
no parent).
PSZ pszclass, Address of a string containing
the name of the window class.
PSZ pszNane, Address of the window text, or
other class-specific data.
ULONG flstyle, The window style.
SHORT x, The horizontal window
position relative to the origin
of the parent window.
SHORT y, The vertical window position
relative to the origin of the
parent window.
SHORT cx, The window width.
SHORT cy, The window height.
Hum hwndowner, Handle of the owner window.
HWND hwndlnsertBehind, Handle of the sibling window
behind which the specified
window is placed; the value
HWND_TOP places the
window on top of all siblings,
and HWND_BOTTOM places
it on the bottom.
USHORT id, The window identifier.

• Figure 12.12..
The Wincreate:Window Presentation Manager function
Exploiting Multitasking and Interprocess Communication 609 .

PVOID pctlData, Address of a buffer containing


class-specific data; this address
is passed to the window
procedure by the
WM CREATE message (Figure
3.16)i
PVOID ppresparams) ,. A reserved field that must be
Zero.

Return Value ..
The handle of the newly created window, or the value NULL
if an error occurred.

Related Functions ..
Wincreatestdwindow (Figure 2.5)

• Figure 12.12..
Tie Wincreatewindow Presentation Manager function ( continued)
611.

his glossary defines many of the terms you may en-

.T
counter while working with the Presentation Manager.
If a term has a special meaning within the context of
OS/2 or the Presentation Manager, this definition is
given rather than the general significance of the word. Note also that
OS/2 is a new and rapidly evolving operating system; you may there-
fore discover inconsistencies in the terminology from one source to
another, as well as general changes over time in the usage of these tech-
nical terms.

accelerator A keystroke that sends a command message


(WM_COMMAND) directly to the client window; it can be used as a
shortcut for issuing a menu command. Accelerators are defined within
a table stored as a program resource and loaded by the Wincreatestd-
Window function.

active application The application that currently owns the ¢cf€.uc


window.

active Window The top-level window that the system places on


top of all other top-level windows; the active window, or one or its des-
cendants, owns the keyboard focus.

alias A segment descriptor that references the same memory seg-


ment as another descriptor.

anchor block handle Anumeric value that identifies a process to


the Presentation Manager (returned by Winlnitialize).

ANSI American National standards Institute. ANsl codes are a set


of escape sequences that can be embedded in video output to control
the console.

API The application program interface, which is a set of services


provided by OS/2 and the Presentation Manager for application
programs.
• 612 Programmer's Guide to the os/2 PresentationManager

argument A value passed to an operating-system command from


the command line, or passed to a function within a program; same as
parameter.

ASCII American Standard Code for Information Interchange; the


encoding scheme that represents the character set used by micro-
computers.

asynchronous Two or more procedures are said to be asyn-


chronous if they occur concurrently, but without timing relationships.
Specifically, if two procedures are asynchronous, when a particular in-
struction is executed in one procedure it is impossible to predict which
instruction is currently being executed in the other procedure. See also
synchronous.

atomic Indivisible; describes a sequence of processor operations


that cannot be interrupted, typically those required to execute a single
machine instruction.

automatic data segment The segment containing a program's


initialized, uninitialized, and constant data, as well as the program
stack and heap.

automatic variable A C program variable declared within the


scope of a function, without using the static or extem keyword; auto-
matic variables are private to each instance of a function, and are stored
within the function's stack frame or machine registers.

background programs Programs executed through the RUN


configuration command, the DETACH command-line instruction, or
from a parent program. These programs are not attached to a screen
group and do not normally interact with the user.

batch file A file containing a sequence of instructions to be ex-


ecuted by a command interpreter; these files have the .BAT extension in
the real mode, and the .CMD extension in the protected mode.
Glossary 613 .

BIOS Basic input-output system; the low-level code that controls


I/0 devices, normally implemented in the read-only memory (ROM)
supplied with the computer.

bitmap A data structure contained in a file or in memory that stores


a graphic image as a sequence of on or off bits indicating the actual
pixel values used to create the image on the screen; see also 77icf¢.Jc.

block To wait for an event without consuming processor cycles. For


example, a thread can block while waiting for an event, and it will be
released by the operating system when the event occurs.

boot disk The disk drive that contains the code used to initialize
the computer and load the operating system when the system is first
reset or powered on.

bound program Same as dt{¢J-777odc progr¢77!.

buffer An area in memory used to temporarily store data that is


read or written in blocks; used to increase the efficiency of data-transfer
operations.

busy waiting Creating a delay, or waiting for a computer event, by


executing a nonproductive program loop.

Cache A high-speed storage area used to improve the efficiency of


accesses to a slower-speed storage medium. For example, temporarily
storing data in a disk cache in random access memory can reduce the
number of accesses required to transfer contiguous blocks of disk data.

cache presentation space A presentation space supplied from


the system's internal collection of presentation spaces; this form of
presentation space can be supplied quickly and without allocating ad-
ditional memory. See prcsc77£¢fz.o77 sp¢cc.

Call gate A special type of segment descriptor that allows a process


to call a subroutine contained within a higher-privileged segment.
•614 Programmer's Guide to the OS/2 Presentation Manager

capturing the mouse Issuing a function call (Winsetcapture)


that causes all subsequent mouse messages to be sent to the issuing
window regardless of the mouse pointer position on the screen (other-
wise, mouse messages are sent to the window that underlies the
pointer).

Caret Same as c#rsor.

Cascade To arrange windows in an overlapping fashion (the presen-


tation Manager default arrangement); see also fz7c.

CGA Color graphics adapter; a standard video controller that


provides graphics with a maximum resolution of 640 by 200 pixels.

Character code A hardware-independent code received by an ap-


plication when the user presses a character key; usually, it is the ASCII
value of the keystroke. See also sc¢# code and uz.rft/¢J-key code.

check box A control window consisting of a small square and an as-


sociated text label, typically contained within a dialog box. Check boxes
are normally displayed within groups, which allow the user to select zero
or more items. When selected, a check box contains a check mark.

Child process A process started by another process (its parent).

child window A window that is displayed within the boundaries


of another window (its parent).

Class A set of attributes, including the address of a window proce-


dure, that define the behavior of a window. A class is registered through
the WinRegisterclass function, and every window must be assigned to
a class when it is created. A window is known as an I.71sfcz7icc of the class
to .which it belongs. .

Click To rapidly press and release a mouse button.

Client window The window created by Wincreatestdwindow


that is typically managed by the application program and used to dis-
play pr`ogram data; it is a child of and is owned by the frame window.
Glossary 615 .

Clip To eliminate data written to the screen or other device that falls
outside of a given boundary.

Clipboard A Presentation Manager facility for transferring data


within a single application or among separate applications.

Code page Atable used to define a character set used by the system.

command processor A program that executes operating-system


commands typed at a prompt. By default, the command processor for
protected mode screen groups is CMD.EXE, and for the real mode
screen group it is COMMAND.COM.

compatibility box The os/2 screen group for running real mode
MS-DOS programs.

Concurrency The simultaneous execution of two or more sequen-


ces of machine instructions; see also 777t/Zfi.£¢sk£.7ig.

control Window A window used to receive input or perform a


specific function;forexample,ascrollbarownedbytheframewindow,
or a push button owned by a dialog box. Control windows typically
send messages to their owners to report user input or other relevant
events.

Cooked mode A state of a character device driver in which it


processes certain characters within the data stream as control codes;
also known as the ASCH 77zodc. See also 7'¢zu 777odc.

Copy To transfer a selected block of data from an application into the


clipboard, leaving the program data intact; see also cwf and p¢sfc.

CPU The central processing unit, or the microprocessor belonging to


a microcomputer.

Critical section Abody of code accessing a program object (such as


a memory location) that cannot be shared by more than one simul-
taneous task.
®616 Programmer's Guide to the OS/2 Presentation Manager

Cursor A highlighted area that marks a particular character position


on tke`e screen, typically indicating the point at which new characters are
inserted into the textual data displayed on the screen.

Cut To remove a selected a block of data from an application and


place it into the Presentation Manager clipboard; see also copy and pflsfc.

deadlock A situation in which one or more tasks is blocked, waiting


for an event that cannot occur.

descriptor A structure in memory maintained by the operating sys-


tern, which contains the physical address of a segment as well as other
information regarding this segment.

descriptor table A table in memory containing a collection of seg-


ment descriptors.

desktop window The entire presentation Manager screen, which


is the parent of all top-level windows.

device context The physical device associated with a presentation


spaLce. see presentation space.

device driver A program that translates operating-system com-


mands into the device-specific code necessary to control a given device.

dialog box A temporary Presentation Manager window that con-


tains a set of control windows for displaying data and obtaining infor-
mation from the user.

dialog-box procedure The function that processes the messages


sent to a dialog box; analogous to a window procedure, which pro-
cesses the messages sent to an application window (usually the client
window).

DOS compatibility box Same as comp¢fi.bz7!.fy box.

double-Click To click a mouse button twice in rapid succession,


while the mouse pointer remains in the same screen area.
Glossary 617 .

drag To press a mouse button and hold the button down while
moving the mouse.

dual-mode program A specially prepared program that can run


under MS-DOS, in the compatibility box of OS/2, or within a protected
mode screen group; the same as a Z7ot/#d p7iogr¢77z.

dynamic linking Linking to a function in a dynamic-link library.

dynamic-link library A file (with the.DLL extension) containing


functions that can be loaded into memory and called by one or more
OS/2programs;adynamic-linklibrarycanalsostoreresourcesthatcan
be accessed by OS/2 programs.

EBCDIC Extended binary-coded decimal interchange code; an


8-bit code for character representation, typically used on IBM minicom-
puters and mainframes.

edit control A control window, typically contained in a dialog box,


that allows the user to enter text.

EGA Enhanced graphics adapter; a standard video controller that


provides graphics with a maximum resolution of 640 by 350 pixels.

event-driven process A process that blocks until it is activated


by an extemal event.

exception A processor error or other internal condition that


generates an interrupt and transfers control to a software routine
designed to handle the event.

expanded memory Memory available to real mode programs


above the normal 640-kilobyte limit. This memory is contained on
special adapter cards and is accessed through a hardware paging
mechanism.

Extended Edition A version of os/2 that contains operating-sys-


tern extensions such as a database manager and a communications
manager.
• 618 Programmer's Guidetothe os/2Presentation
Manager

extended memory Memory contained in 80286/80386 machines


at addresses above 1 megabyte. This memory space can be directly ac-
cessed only in protected mode.

external variable A C program variable declared outside the


scope of an individual function.

Family API A subset of the os/2 Apl functions that can be called
by dual-mode programs when they are running in real mode.

far address An address containing both a 16-bit segment seJecfor (in


the protected mode, or the ¢dd71ess in the real mode) and a 16-bit o#sc£
within this segment. See also 71c¢r ¢dczrcss.

:::rudsm¥ag:sY The Window to Which the system sends all key_

font A collection of bitmaps defining the shape of each character


within a given character set.

frame Window The top-level window created by Wincreatestd-


Window,whichownsandistheparentoftheotherwindowsgenerated
by this function.

gigabyte 230, or approximately one billion, bytes.

global descriptor table A table maintained in memory contain-


ing the descriptors for segments that can be accessed by au processes;
see also local descriptor table.

handle A numeric value returned by many os/2 and presentation


Managerfunctionsusedtoidentifytheownerofaprogramobject(such
as an open ffle or a window) when subsequent function calls are made.

heap Ablock of memory out of which smaller blocks of memory are


dynamically allocated.

hotkey The keystroke that activates a background program (under


OS/2, usually a monitor).
Glossary 619 .

hot spot A single, specially designated pixel within a mouse


pointer;thepositionofthemousepointerisspecifiedasthecoordinates
of the hot spot.

huge memory allocation A block of allocated memory consist-


ingofmorethanonesegment.Thesegmentsneednotbecontiguousin
memory, but the selectors for these segments differ numerically by a
constant amount.

icon A fixed-size graphic image that you can create and display
within a Presentation Manager application; an application window is
represented by an icon when it is minimized.

import library A library file that resolves references to dynamic-


link functions by supplying records that contain the module name and
entry point for the function, but not the actual code.

interprocess communication Sending signals or exchanging


data among separate threads or processes.

intelTupt A software, hardware, or processor-generated event that


passescontroltoaroutineinmemorythatprovidesaserviceorhandles
a condition.

interrupt routine The device driver entry point invoked by


hardware interrupts that are generated by the associated device; see
also strategy routine.

invalidate To add a section of a window to its t4pd¢fc rcg€.o7i, which


is the area of the window that must be redrawn during processing of
the WM_PAINT message.

I/0 Privilege Permission granted to a specific code segment to


issuedirectport1/0instructionsortoenableordisablehardwareinter-
rupts (under OS/2, a segment with I/0 privilege runs at privilege
level 2).
• 620 Programmer's Guide to the os/2Presentation
Manager

kernel The core operating-system code that operates at the highest


privilege level; also, the portion of the API exclusive of the Presentation
Manager and other operating-system extensions.

5ree::net]at::np#::::I A program not written specifically for the

kilobyte 210, or 1024,bytes.

list box A rectangular control window (typically belonging to a


dialogbox)thatcontainsaverticalscrollbarandisusedtodisplayalist
of strings.Theusercanscrollthroughthelistofstrings,andcanselecta
given string.

local descriptor table A table maintained in memory containing


the descriptors for segments that can be accessed by a specific process;
see aLiso global descriptor table.

maximize To enlarge a window to its maximum size, which fills


most of the screen.

maximize box A control window displaying an upward-pointing


arrow; when the user clicks the mouse with the pointer within this con-
trol, the owner (or parent) window is maximized.

megabyte 220, or approximately 1 million, bytes.

menu A control window used to display a list of commands; the


user issues a command by selecting the associated item from the menu.

message queue A data structure associated with a Presentation


Manager program thread, which is used to store messages posted to
any of the windows created by that thread.

metafile A data structure contained in a disk file or in memory that


stores a graphic image as a sequence of Presentation Manager com-
mands required to create the image; see also bz.£77z¢p.

minimize To reduce a window to an icon on the screen.


Glossary 621 .

minimize box A control window displaying a downward-point-


ing arrow; when the user clicks the mouse with the pointer within this
control, the owner (or parent) window is minimized.

modal Describes a dialog box that does not allow the user to switch
the focus to another window owned by the same application, until the
dialog box is dismissed. A sysfeffl 7ttod¢J dialog box disallows the user
from switching the focus to any other window in the system.

monitor An os/2 program that processes the stream of characters


passing to or from a character device.

mouse An input device that moves a pointer on the screen as it is


moved on the desk surface; a mouse also has one to three buttons that
transmit information to the program.

multiprocessing Simultaneous execution of code by more than


one processor in a single computer.

multitasking Simultaneous execution of more than one sequence


of machine instructions.

multiuser Refers to a single computer connected to more than one


terminal, which allows several users to share the same processor. Note
that OS/2 is 71of a multiuser system.

near address An address consisting of only a 16-bit offset. See also


far address.

object window A presentation Manager window used to receive


messages; an object window is not displayed on the screen, does not
receive input messages, and does not have a parent.

overcommitment (of memory) Allocation of more memory


than is physically present in the machine; accomplished by swapping
segments between memory and secondary storage on a disk.
•622 Programmer's Guide to the OS/2 Presentation Manager

Parameter A value passed to an operating-system command from


the command line, or passed to a function within a program; same as
argument.

Parent process A process that starts another process (its child).

£oa::::e¥isnpTa°y¥d.Awfnd°Wwithinwhichoneormorechi|dwin_

Paste To insert a block of data from the presentation Manager clip-


boardintothedatabelongingtoanapplication;seealsoc%£andco".

Path The fun specification of the location and name of a disk ffle, in-
cluding the drive, directory, and file name.

Pipe A form of interprocess communication that allows two related


processes to exchange a serial stream of data.

Pixel Picture element; smallest unit on the screen that can be control-
led(tumedonoroff,orassignedacolororintensity).

Point To place the hot spot of the mouse pointer on a given item or
within a given area.

Pointer A fixed-size graphic image that is moved on the screen in


response to movements of the mouse, or in response to program func-
tion calls.

Poll To test for the occurrence of a specific event; for example, an in-
efficient program might repeatedly poll for the arrival of a character
rather than blocking.

Port An input-output address that can be used to control a device.

Post To place a message in a presentation Manager message queue.

Preempt To take control away from a particular task in a multitask-


ing system (rather than letting the task voluntarily yield control). OS/2
is a preemptive multitasking system.
Glossary 623 .

Presentation Manager An operating-system extension provided


withOS/2versions1.1andlater,whichprovidesawindowedgraphics
interface similar to Microsoft Windows.

Presentation Manager application A program written speci-


fically for the Presentation Manager, which performs the necessary in-
itializations and calls Presentation Manager API functions.

presentation space The abstract space onto which a presentation


Managerapplicationdisplaysdata;itmustbeassociatedwithaphysi-
cal device (the device associated with a presentation space is known as
the det)€.ce co7ifexf). A presentation space is maintained as a data struc-
ture by the system, and it is assigned device-independent attributes,
such as a current set of colors and a current font.

Priority A value assigned to each thread in the system that allows


the scheduler to determine which thread among those ready to run
should be dispatched.

privilege The set of permissions associated with a particular seg-


ment. There are four privilege levels, numbered from 0 (the highest
privilegelevel,reservedfortheoperatingsystem)to3(thelowestprivi-
lege level, for application programs).

Process A single instance of the execution of a program.

Program A collection of code and data stored in an executable file


and loaded into memory at run-time.

protect To prevent a given process from cormpting other processes


in a multitasking system; OS/2 uses the hardware protection
mechanisms provided by the 80286 processor.

protected mode A processor state of the 80286/80386 processors


that allows the operating system to safely run multiple tasks and pro-
vide virtual memory; same as z7t.rftz¢J 7ttode.
•624 Programmer's Guide to the OS/2 Presentation Manager

Protection fault A processor exception generated when an ap-


plication attempts to violate the protection mechanisms enforced in the
protected mode. See also exccpfz.o77.

Push button A small, rectangular control window with rounded


corners and a text label that can be selected (``pushed'') by the user to
initiate an action.

queue A form of inteaprocess communication provided by OS/2;


specifically, an ordered collection of messages that have been sent from
one or more processes to a single receiving process (71of related to a
Presentation Manager 77zcss¢gc 7#c#C).

radio button A control window consisting of a small circle with an


associatedtextlabel,typicallydisplayedwithinadialogbox.Radiobut-
tonsareusuallyplacedingroupsthatallowtheusertoselectonlyo7ieof
the items (that is, they are used for mutually exclusive choices); when a
radiobuttonisselected,theinsideofthecircleishighlighted.

RAM Random access memory; the randomly addressable, volatile


main memory used to store programs and data.

raw mode A state of a character device driver in which it passes an


charactersasriteralvalues,anddoesnotrespondtocontrolcodesembedded
in the data stream; also known as b£.#¢ny fflodc. See also cooked 77iocze.

real mode A processor state of the 80286/80386 processors that


emulates the operation of the 8086/8088 processors.

real mode screen group Same as co77tp¢f{.b€.J2.rty box.

reentrant Abody of code is reentrant if it can be executed more than


once at a given time.

resource A collection of read-only data stored within an executable


fileorinadynamic-linklibrary.Thesedataareinserteddirectlyintothe
file by a resource compiler, and they are loaded into memory when re-
quired by an application.
Glossary 625 .

resource compiler Autility that translates a text script into binary


resource data, and inserts these data directly into an executable file.

resource script Atext file that defines a set of os/2 resources.

ROM Read-only memory; nonvolatile memory supplied with


microcomputers that normally contains code to control hardware
devices.

Scan code A hardware-specific code emitted by the keyboard to in-


dicate the key that has been pressed or released; see also cfeflr¢cfcr code
a;nd virtual-key code.

Scheduler The portion of the operating system that apportions


CPU time among multiple threads and determines the priority of each
thread.

Screen group A collection of processes that share a single virtual


screen, keyboard, and mouse.

Scroll To move a block of data displayed within a window toward


one of the four window borders.

scroll bar A control window used to scron textual data within a win-
dow.Ahorizontalscroubaristypicauylocatedalongtheloweredgeofits
parentandscroustexthorizontally;averticalscroubaristypicallylocated
alongtherightedgeofitsparentandscroustextverticany.

segment A variable-length block of allocated memory together


with a set of attributes (such as the privilege level).

segment descriptor Same as dcscrz.pfor.

Selector The virtual address of a memory segment, which serves as


an index into a table containing the actual physical address; the selector
isloadedintoasegmentregister,suchasDS,toaddressthecorrespond-
ing segment.
• 626 Programmer's Guide to the os/2 Presentation
Manager

Semaphore A software flag used to synchronize the activities of


two or more threads of execution.

Serialize To ensure that a given object can be accessed by only one


thread at a time; access to an object is typically serialized by means of a
semaphore.

Server The process that owns a queue and receives the queue messages.

Session The same as a scrcc77 groz4p.

Session manager A system utility that manages switching among


screen groups; if the Presentation Manager is installed, this function is
performed by the Task Manager.

Sizing border A control window that forms a wide border around


its parent window; it can be used to adjust the parent window size with
the mouse.

SPooler A background program that stores printer output in tern-


porary files and prints these files in a given order.

Stack A data structure in memory that holds the parameters and


local variables belonging to a function while the function is active. It is
alsousedforthetemporarystorageofregistercontentsormemoryvari-
ables. Items placed on the stack are said to be p#sfeed, and items
removed are popped; items are stored within the stack on a last-in, first-
out basis, and with Intel processors the stack grows dozo71zu¢rd in
memory (that is, toward lower addresses) as values are pushed.

Strategyroutine The device driver entry point called by the


operating system to request a device service; see also I.7iferr%pf 71o#£2.7ie.

Subsystem A set of dynamic-link functions that control a common


resource, such as the OS/2 video-management functions that are
named with the Vz.o prefix.
Glossary 627 .

Swapping The temporary storage of memory segments on disk to


make room for other segments. This mechanism is useful when
rr\errrory is overcommitted.

Synchronous Two procedures are said to be synchronous if their


actions occur in a specific order. For example, if one procedure waits at
agivenpointuntilasecondprocedurecompletes,theseproceduresare
said to be synchronous. See also ¢sy7tcfero7io%s.

task A general term referring to one of the concurrent threads or


processes of a multitasking system.

thread The basic dispatchable entity under os/2; the execution of a


series of machine instructions within a program.

tile To arrange windows in a side-by-side, nonoverlapping fashion;


see also cosc¢de.

time Slice The period of time that the scheduler allows a thread to
run before it grants CPU time to another thread of equal priority.

title bar A control window typically located along the top edge of
its parent; the title bar contains a text title and is used for moving the
parent window with the mouse.

top-level window A window that is the direct child of the desk-


top window; also known as a 771¢£.ro window.

TSR A terminate-and-stay-resident program under MS-DOs or the


DOS compatibility box of OS/2. These programs remain loaded in
memory while the user runs other applications in the foreground.

typamatic Refers to the automatic repeated generation of key-


strokes when a key is held down.

update region The invalid area of a window that must be updated


by the routine that processes the WM_PAINT message.
•628 Programmer's Guide to the OS/2 Presentation Manager

VGA Video graphics array; a standard video controller that normal-


lyprovidesagraphicsresolutionupto640by480pixels.

virtual-key code A set of device-independent codes used to iden-


tify keys that do not have standard character codes; for example, the
functionorarrowkeyscanbeidentifiedthroughvirtual-keycodes.See
aL+so character code a;nd scan code.

Virtual memory The allocatable memory space in protected mode,


which may exceed the amount of physical memory installed in the
machine.Segmentswithinthisspacemaybetemporarilyswappedtoa
disktomakeroomforsegmentsthatarecurrentlybeingreferenced.

Virtual mode Same as profccfcd 777odc.

Window The fundamental object owned by a presentation Manager


application, which can receive messages and is typically associated
with a rectangular area on the screen used to interact with the user.

window class SeecJ¢ss.

window procedure The function that processes the messages


sent to a given window (when a message is sent, the system c¢JJs this
procedure, passing the content of the message as parameters).

word A two-byte data value; stored in memory with the low-order


byte first(thatis,attheloweraddress),followedbythehigh-orderbyte.
631.

his appendix provides a brief alphabetical summary of

.T
the Presentation Manager and OS/2 functions that have
been described in the book. The synopsis of each func-
tion provides a short statement of the function's pur-
pose, the function prototype, and a reference to the figure in the book
that fully describes the function. Note that the inside book covers list
these same functions according to the types of services they provide.
Note also that the functions described in this book are a subset of the
full set of services offered by OS/2 and the Presentation Manager; see
the technical documentation cited in the Bibliography for information
on functions not covered in the book.

• DosAllocseg
Purpose..
Allocates a memory segment.

Prototype..
USHORT APIENTRY DosAllocseg
(USHORT ussize,
PSEL psel,
USHORT fAIloc) ,.

Figure..
9.1

• DoscreateThread
Purpose..
Starts a new thread of execution within the current process.

Prototype..
USHORT APIENTRY DoscreateThread
(VOID PASCAL FAR *pfnFunction (VOID) ,
PTID ptidThread,
PBYTE pbThrdstack) ,.
• 632 Programmer's Guide to the os/2Presentation
Manager

Figure..
12.1

• DosExit
Purpose..
Terminates either a single thread or an entire process.

Prototype..
VOID APIENTRY DosExit
`,, (USHORT fTerminate,
USHORT usExitcode) ,.

Figure..
12.5

• DosGetResource
Purpose..
Loads the specified resource segment into memory.

Prototype..
USHORT APIENTRY DosGetResource
(HMODUI.E hmod,
USHORT idType,
USHORT idNane,
PSEL psel) '.

Figure..
10.26

• DosGetseg
Purpose..
Secures access to a shared memory segment for the current
process.
SelectedpresentationManagerFunctions 633 .

Prototype..
USHORT APIENTRY DosGetseg
(SEL sel) '.

Figure..
9.7

• Dossemclear
Puxpose..
Clears the specified semaphore.

Prototype..
USHORT APIENTRY Dossemclear
(HSEM hsem) ,.

Figure..
12.7

• Dossemset
Purpose..
Sets the specified semaphore.

Prototype..
USHORT APIENTRY Dossemset
(HSEM hsem) ,.

Figure..
12.6

• Dossemwait
Purpose..
Waits, if necessary, for the specified semaphore to be cleared,
or until the given timeout has elapsed.
• 634 Programmer'sGuide tothe os/2Presentation
Manager

Prototype..
USHORT APIENTRY Dossemwait
(HSEM hsen,
LONG ITimeout) ,.

Figure..
Figure 12.8

• Dossizeseg
Purpose..
Obtains the size in bytes of a specified memory segment.

Prototype..
USHORT APIENTRY Dossizeseg
(SEL selpuLONG pulsize) ,.

Figure..
10.27

• GpicharstringAt
Purpose..
Draws a line of text at a specified starting position.

Prototype..
LONG APIENTRY GpicharstringAt
(HPS hps,
PPOINTL pptlstart,
LONG cchstring,
PCH pchstring) ,.

Figure..
3.28
SelectedpresentationManagerFunctions 635 .

• GpicreateLogFont
Purpose..
Creates a logical definition of a font.

Prototype..
BOOL APIENTRY GpicreateLogFont
(HPS hps,
PSTR8 pchNane,
LONG lcid,
PFATTRS pfat) ,.

Figure..
3.26

• GpiDeleteBitmap
Purpose..
Frees a bitmap.

Prototype..
BO0L APIENTRY GpiDeleteBitmap
(HBIT"ZP hbm) ,.

Figure..
10.23

• GpiErase
Purpose..
Erases the display device associated with the specified
presentation space using the default system background
color (CLR BACKGROUND).

Prototype..
BOOL APIENTRY GpiErase
(HPS hps) ,.
• 636 Plogrammer's Guidetothe os/2Presentation
Manager

Figure..
10.12

• GpiLine
Purpose..
Draws a straight line from the current graphics position to
the specified endpoint, and resets the current graphics posi-
tion to this endpoint.

Prototype..
LONG APIENTRY GpiLine
(HPS hps,
PPOINTL pptl) ,.

Figure..
11.23

• GpiLoadBitmap
Purpose..
Loads a bitmap from a resource segment into memory.

Prototype..
HBI"AP APIENTRY GpiLoadBitmap
(HPS hps,
USHORT module,
USHORT idBitmap,
LONG Iwidth,
LONG IHeight) ,.

Figure..
10.21

• GpiLoadFonts
Purpose..
Loads one or more fonts from a font file.
Selected Presentation Manager Functions 637.

Prototype..
Boor. APIENTRY GpiLoadFonts
(RE hab,
PSZ pszFilename) ,.

Figure..
3.18

• GpiMOve
Purpose..
Sets the current graphics position.

Prototype..
BOOL APIENTRY GpiMove
(HPS hps,
PPOINTL pptl) ,.

Figure..
11.22

• GpiQueryFonts
Purpose..
Returns information on one or more of the fonts that are cur-
rently available.

Prototype..
LONG APIENTRY GpiQueryFonts
(HPS hps'
ULONG floptions,
PSZ pszFacename,
PLONG pcFonts,
LONG cbMetrics
PFONTMETRICS pfmMetrics) ,.

Figure..
3.20
• 638 Programmer's Guide tothe os/2Presentation
Manager

• GpisetBackcolor
Purpose..
Sets the background color generated by graphics functions
such as GpicharstringAt.

Prototype..
BO0L APIENTRY GpisetBackcolor
(HPS hps'
LONG IColor) ,.

Figure..
9.9

• GpisetBackMix
Purpose..
Specifies the way the background color generated by
graphics functions (such as GpicharstringAt) is combined
with the existing color within the presentation space.

Prototype..
BOOL APIENTRY GpisetBackMix
(HPS hps,
LONG IMi"ode) ,.

Figure..
9.8

• Gpisetcharset
Purpose..
Setsthecurrentcharactersetusedfordisplayingtextualdata
within the specified presentation space.
Selected Presentation Manager Functions 639.

Prototype..
BOOL APIENTRY Gpisetcharset
(HPS hps'
I.ONG lcid) ,.

Figure..
3.27

• Gpisetcolor
Purpose..
SetstheforegroundcolorusedbyGp€.functionssuchasGpi-
CharstringAt.

Prototype..
BOOL APIENTRY Gpisetcolor
(HPS hps'
LONG IColor) ,.

Figure..
3.29

• WinAlarm
Purpose..
Sounds the computer speaker.

Prototype..
BOOL APIENTRY WinAlarm
(HWND hwndDesktop,
USHORT rgfType) ,.

Figure..
6.9
• 640 Programmer's Guide to the os/2Presentation
Manager

• WinAllocMem
Purpose..
Allocates a block of memory from a Presentation Manager
heap.

Prototype..
NPBYTE APIENTRY WinAllocMem
(HHEAI hHeap,
USHORT cb) ,.

Figure..
3.7

• WinBeginpaint
Purpose..
Obtains a handle to a presentation space that is associated
with the specified window.

Prototype..
IIPS APIENTRY WinBeginpaint
(HIND hwnd,
HPS hps,
PRECTL prclpaint) ,.

Figure..
2.20

• Wincloseclipbrd
Purpose..
Closes the clipboard, previously opened through Winopen-
Clipbrd.
SelectedpresentationManagerFunctions 641 .

Prototype..
BOOL APIENTRY Wincloseclipbrd
(HAB hab) ,.

Figure..
9.4

• Wincreatecursor
Puxpose..
Creates a cursor within the specified window.

Prototype..
BOOL APIENTRY Wincreatecursor
(HIND hwnd,
SHORT x,
SHORT y,
SHORT cx,
SHORT cy,
USHORT fs,
PRECTL prclclip) ,.

Figure..
5.3

• WincreateHeap
Purpose..
Creates and initializes a heap for dynamically anocating
blocks of memory.

Prototype..
HHEAP APIENTRY WincreateHeap
(USHORT selHeapBase,
USHORT cbHeap,
USHORT cbGrow,
USHORT cbMinDed,
• 642 Programmer's Guide to the os/2Presentation
Manager

USHORT cbMaxDed,
USHORT fQptions) ,.

Figure..
Figure 3.4

• WincreateMsgQueue
Purpose..
Establishes a message queue that receives messages sent to
all windows created by the current thread.

Prototype..
HinQ APIENTRY WincreateMsgQueue
(HAB hab,
SHORT cmsg) ,.

Figure..
2.3

• Wincreatestdwindow
Purpose:
Creates a standard window.

Prototype..
HWND APIENTRY Wincreatestdwindow
(HEED hwndparent ,
ULONG flstyle,
PVOID pctlData,
PSZ pszclientclass,
PSZ pszTitle,
ULONG styleclient,
"ODULE hood,
USHORT idResources,
PHWND phwndclient) ,.
SelectedpresentationManagerFunctions 643 .

Figure..
2.5

• Wincreatewindow
Puxpose..
Creates a new window.

Prototype..
HWND APIENTRY Wincreatewindow
(HIND hwndparent ,
PSZ pszclass,
PSZ pszNane,
ULONG flstyle,
SHORT x,
SHORT y,
SHORT cx,
SHORT cy,
IIWND hwndowner ,
HWND hwndlnsertBehind,
USHORT id,
PVOID pctlData,
PVOID ppresparams) ,.

Figure..
12.12

• WinDefDlgproc
Puxpose..
Provides default processing for a message sent to a dialog
procedure.

Prototype..
ULONG APIENTRY WinDefDlgproc
(HIND hwndDlg,
` USHORT msgid,
• 644 Programmer's Guide to the os/2Presentation
Manager

mARAI mpl,
REARAM mp2) ,.

Figure..
8.10

• WinDefwindowproc
Purpose..
Passesamessagetothesystemfordefaultprocessing.

Prototype..
IflESULT APIENTRY WinDefwindowproc
(HIND hwnd,
USHORT msg,
REAEN mpl,
REARAI mp2) ,.

Figure..
2.17

• WinDestroycursor
Purpose..
Destroys the cursor associated with the specified window.

Prototype..
BOOL APIENTRY WinDestroycursor
(HIND hwnd) ,.

Figure..
5.6

• WinDestroyHeap
Purpose..
Destroys a heap previously created by WincreateHeap.
Selected Presentation Manager Functions 645.

Prototype,
HHEAP APIENTRY WinDestroyHeap
(HHEAI hHeap) ,.

Figure..
3.5

• WinDestroyMsgQueue
Purpose..
Destroys the specified message queue.

Prototype..
BOOL APIENTRY WinDestroyMsgQueue
(HMQ hmq) ,.

Figure..
2.14

• WinDestroypointer
Purpose..
Destroys an icon or pointer.

Prototype..
Boot- APIENTRY WinDestroypointer
(HPOINTER hptr) ,.

Figure..
10.10

• WinDestroywindow
Purpose..
Destroys the specified window and all its descendant
windows.
•646 Programmer's Guide to the OS/2 Presentation Manager

Prototype..
BOOL APIENTRY WinDestroywindow
(HEAD hwnd) ,.

Figure,
2.13

• WinDismissDlg
Purpose..
Removes the current dialog box and causes the function
WinDlgBox to return control.

Prototype..
B00L APIENTRY WinDismissDlg
(HIND hwncolg,
USHORT usResult) ,.

Figure..
8.11

• WinDispatchMsg
Purpose..
Causes the system to call a window procedure.

Prototype..
ULONG APIENTRY WinDispatchMsg
(HAB hab,
PQMSG pqusg) ,.

Figure..
2.9

• WinDlgBox
Purpose..
Loads, displays, and processes a dialog box.
Selected Presentation Manager Functions 647 .

Prototype..
USHORT APIENTRY WinDlgBox
(HIND hwncaparent ,
HWND himdoimer ,
PFrm pfhDlgproc,
"ODULE hmod,
USHORT idDlg,
PVOID pcreateparams) ,.

Figure..
8.9

• WinDrawBitmap
Purpose..
Draws a bitmap within the specified presentation space.

Prototype..
BOOL APIENTRY WinDrawBitmap
(HPS hpsDst,
HBITur ham,
PRECTL pwrcsrc,
PPOINTL pptlDst,
LONG clrFore,
LONG clrBack,
USHORT fs) ,.

Figure..
10.22

• WinDrawpointer
Purpose..
Draws an icon.

Prototype..
BOOL APIENTRY WinDrawpointer
(HPS hps,
•648 Programmer's Guide to the OS/2 Presentation Manager

SHORT x,
SHORT y,
HPOINTER hptr,
USHORT fs) ,.

Figure..
10.9

• WinDrawText
Purpose..
Printsatextstringwithinaspecifiedrectangle,usingthecur-
rent font.

Prototype..
SHORT APIENTRY WinDrawText
(HPS hps,
SHORT cchText,
PCH pchText,
PRECTL prcl,
LONG clrFore,
LONG clrBack,
USHORT rgfchd) ,.

Figure..
2.24

• WinEmptyclipbrd
Purpose..
Removes all data blocks from the clipboard, freeing the as-
sociated data handles.

Prototype..
BOOL APIENTRY WinEmptyclipbrd
(RED hab) ,.
Selected Presentation Manager Functions 649 .

Figure..
9.6

• WinEnablewindow
Purpose..
Enables or disables the specified window.

Prototype..
BOOL APIENTRY WinEnablewindow
(HIND hwnd,
BOOL fEnable) ,.

Figure..
4.10

• WinEndpaint
Purpose..
Signalsthesystemthattheupdatingofthewindow(which
occurs typically in response to a WM_PAINT message) is
complete.

Prototype..
BO0L APIENTRY WinEndpaint
(HPS hps) '.

Figure..
2.21

• WinFillRect
Purpose..
Draws a rectangle filled with a specified color.

Prototype..
BOOL APIENTRY WinFillRect
(HPS hps'
•650 Programmer's Guide to the OS/2 Presentation Manager

PRECTL pcrl,
LONG IColor) ,.

Figure..
2.23

• WinFreeMem
Purpose..
FreesamemoryblockfromaheapmanagedbythePresenta-
tion Manager.

Prototype..
NPBYTE AVIENTRY WinFreeMem
(HREAP hHeap,
REBYTE npMen,
USHORT cbMem) ,.

Figure..
3.10

• WinGetKeystate
Purpose..
Determines whether a virtual key or mouse button is cur-
rently pressed or released; also returns the toggle status of
a key.

Prototype..
SHORT APIENTRY WinGetKeystate
(HIND hwndDesktop,
SHORT vkey) ,.

Figure..
11.16
Selected Presentation Manager Functions 651 .

• WinGetLastError
Puxpose..
Returns the system error code set by the last Presentation
Manager function that failed, and resets the system error
code to 0.

Prototype..
EREORID APIENTRY WinGetLastError
(HID hab) '.

Figure..
3.11

• WinGetMsg
Purpose,
Extracts the next message from the message queue belong-
ing to the current thread.

Prototype..
BOOL APIENTRY WinGetMsg
(us hab,
PQMSG pqusg,
HWND hwndFilter,
USHORT msgFilterFirst ,
USHORT msgFilterLast) ,.

Figure..
2.8

• winGetps
Purpose..
Obtains a cache presentation space.
•652 Programmer's Guide to the OS/2 Presentation Manager

Prototype..
HPS APIENTRY WinGetps
(HEAD hund) ,.

Figure..
3.19

• Winlnitialize
Purpose..
Initializes the Presentation Manager system for use by the
current program.

Prototype..
HAB APIENTRY Winlnitialize
(USHORT foptions) ,.

Figure..
2.2

• WinlnvalidateRect
Purpose..
Addsarectangularareatoawindow'supdateregion.

Prototype..
B00L APIENTRY WinlnvalidateRect
(HIND hwnd,
PRECTL prcl,
Boor. f Includechildren) ,.

Figure..
5.8
Selected Presentation Manager Functions
653.

• WinLoadpointer
Purpose..
Loads an icon or mouse pointer into memory from a
resource segment contained in a disk file.

Prototype..
HPOINTER APIENTRY WinLoadpointer
(HIND hwndDesktop,
"ODUI.E hood,
USHORT idres) ,.

Figure..
10.8

• WinLoadstring
Purpose..
Loads a string from a string table resource into a program
buffer.

Prototype:
SHORT APIENTRY WinLoadstring
(HAB hab,
"ODUI.E hood,
USHORT id,
SHORT cc"ax,
PSZ pchBuf fer) ,.

Figure..
10.25

• WinLockHeap
Purpose..
Supplies the far address of the base of the segment contain-
ing the specified heap.
®654 Programmer's Guide to the OS/2 Presentation Manager

Prototype..
PVOID APIENTRY WinLockHeap
(HREAP hHeap) ,.

Figure..
3.6

• WinMapwindowpoints
Purpose..
Maps the coordinates of one or more points from the coor-
dinate space relative to one window into the coordinate
space relative to another window.

Prototype..
BcOL APIENTRY WinMapwindowpoints
(HIND hwncITrom,
HWND hundTo,
PPOINTL pptl,
SHORT cxpt) r.

Figure..
11.4

• WinMessageBox
Purpose..
Displays a message box window.

Prototype..
USHORT APIENTRY WinMessageBox
(HIND hwndparent ,
Hue hundormer,
PSZ pszText,
PSZ pszcaption,
USHORT idwindow,
USHORT flstyle) ,.
Selected Presentation Manager Functions 655.

Figure..
3.14

• Winopenclipbrd
Puxpose..
Opens the clipboard for the current thread, to provide this
thread exclusive access to the clipboard.

Prototype..
BOOL APIENTRY Winopenclipbrd
(RED hab) ,.

Figure:
9.2

• WinpostMsg
Purpose..
Posts a message to the message queue belonging to the
specified window.

Prototype..
BOOL APIENTRY WinpostMsg
(Hum hwnd,
USHORT msg,
REAEN mpl,
reJ-mp2) ,.
Figure..
12.11

• WinQueryclipbrdData
Purpose..
Returns a handle to the block of data in the clipboard that
has the requested format.
•656 Programmer's Guide to the OS/2 Presentation Manager

Prototype..
ULONG APIENTRY WinQueryclipbrdData .,

(RE hab,
USHORT fmt) ,.

Figure..
9.5

• WinQueryFocus
Puxpose..
Obtains the handle of the focus window.

Prototype..
HWND APIENTRY WinQueryFocus
(HEED hwndDesktop,
BOOL fLock) ,.

Figure..
5.10

• WinQueryMsgpos
Purpose,
Obtains the position of the mouse pointer at the time the last
message extracted from the message queue was posted. The
position is given in screen coordinates.

Prototype..
BOOL APIENTRY WinQueryMsgpos
(HRE hab,
PPOINTL pptl) '.

Figure..
11.3
SelectedpresentationManagerFunctions 657 .

• WinQuerypointerpos
Purpose..
Obtains the current position of the mouse pointer in screen
coordinates.

Prototype..
BOOL APIENTRY WinQuerypointerpos
(HWND hwndDesktop,
PPOINTL pptl) '.

Figure..
11.2

• WinQuerysyspointer
Purpose..
Returns the handle to the requested system pointer or icon.

Prototype..
HPOINTER APIENTRY WinQuerysyspointer
(HWND hwndDesktop,
SHORT iptr,
BOOL fLoad) ,.

Figure..
11.7

• WinQuerysysvalue
Puxpose..
Returns the specified system value.

Prototype..
LONG APIENTRY WinQuerysysvalue
(HWND hwndDesktop,
SHORT isysvalue) ,.
• 658 Programmer's Guide to the os/2Presentation
Manager

Figure..
11.1

• WinQuerywindow
Purpose..
Returns the handle of the window that has the selected
relationship to a specified window.

Prototype..
HWND APIENTRY WinQuerywindow
(HIND hwnd,
SHORT cnd,
BOOL fLock) ,.

Figure..
4.6

• WinQuerywindowRect
Purpose..
Returns the coordinates of the specified window.

Prototype..
BOOL APIENTRY WinQuerywindowRect
(HIND hwnd,
PRECTL prclDest) ,.

Figure..
2.22

• WinQuerywindowText
Purpose,
Copies the text associated with a window into a program
buffer.
SelectedpresentationManagerFunctions 659 .

Prototype..
SHORT APIENTRY WinQuerywindowText
(HIND hwnd,
SHORT cchBufferMax ,
PSZ pszBuffer) ,.

Figure..
8.16

• WinRegisterclass
Purpose..
Registers a window class.

Prototype..
BOOL APIENTRY WinRegisterclass
(mD hab,
PSZ pszclassName,
PFNWP pfnwndproc ,
ULONG flstyle,
USHORT cbwindowData) ,.

Figure..
2.4

• WinReleaseps
Purpose..
ReleasesthepresentationspaceobtainedthoughWinGetps.

Prototype..
BOOL APIENTRY WinReleaseps
(HPS hps) ,.

Figure..
3.22
• 660 Programmer'sGuidetothe os/2Presentation
Manager

• Winscrollwindow
Purpose..
Scrolls the contents of a window a specified horizontal and
vertical distance.

Prototype..
SHORT APIENTRY Winscrollwindow
(HEED hwnd,
SHORT ck,
SHORT dy,
PRECTL prclscroll,
PRECTL preclclip,
HRGN hrgnupdate,
PRECTL prclupdate,
USHORT rgfsw) ,.

Figure..
4.14

• WinsendDlgltemMsg
Purpose..
Sends a message to a child control window within a dialog
box; the target control window is specified by its identifier
and the parent window handle (rather than by its own win-
dow handle).

Prototype..
MRESULT APIENTRY WinsendDlgltelhMsg
(HEAD hwndDlg,
USHORT idltem,
USHORT msg,
ueAEun mpl ,
mAIRAM mp2) ,.
Selected Presentation Manager Functions 661.

Figure..
8.25

• WinsendMsg
Purpose..
Sends a message to the specified window.

Prototype:
lmESULT APIENTRY WinsendMsg
(HIND hwnd,
USHORT msg,
REARAI "pl ,
REARAI mp2) ,.

Figure..
4.8

• WinsetclipbrdData
Puxpose..
Places a block of data into the clipboard.

Prototype..
BOOL APIENTRY WinsetclipbrdData
(HJD hab'
ULONG ulData,
USHORT fmt,
USHORT rgfFmtlnfo) ,.

Figure..
9.3

• WinsetFocus
Puxpose..
Assigns the focus to the specified window.
• 662 Programmer's Guide to the os/2Presentation
Manager

Prototype..
BOOL APIENTRY WinsetFocus
(HEED hwndDesktop,
HWND hwndsetFocus) ,.

Figure..
4.3

• Winsetpointer
Purpose..
Sets the mouse pointer that is displayed by the system.

Prototype..
BOOL APIENTRY Winsetpointer
(HIND hwndDesktop,
HPOINTER hptrNew) ,.

Figure..
11.6

• Winsetpointerpos
Purpose..
Sets the position of the mouse pointer.

Prototype..
B00L APIENTRY Winsetpointerpos
(HEAD hwndDesktop,
SHORT x,
SHORT y) '.

Figure..
11.11
SelectedpresentationManagerFunctions 663 .

• WinsetwindowText
Puxpose..
Sets the text associated with a window.

Prototype..
BOOL APIENTRY WinsetwindowText
(HIND hwnd,
PSZ pszText) ,.

Figure..
7.18

• Winshowcursor
Purpose..
Makes visible or hides the cursor associated with the
specified window.

Prototype..
BOOL APIENTRY Winshowcursor
(HIND hwnd,
BOOL f show) ,.

Figure..
5.5

• Winshowpointer
Purpose..
Shows or hides the mouse pointer by changing the pointer
hide level.

Prototype..
BOOL APIENTRY Winshowpointer
(HWND hwndDesktop,
BOOL f show) ,.
®664 Programmer's Guide to the OS/2 Presentation Manager

Figure..
11.10

• WinTerminate
Purpose..
Signals the Presentation Manager that the calling thread has
completed using the services of the Presentation Manager,
and releases all Presentation Manager resources held by this
thread.

Prototype..
BOOL APIENTRY WinTerminate
(HAB hab) ,.

Figure..
2.15

• Winupdatewindow
Purpose..
Causes the system to send a WM_PAINT message to the
specified window by directly calling the window procedure.

Prototype..
B00L APIENTRY Winupdatewindow
(HEED hwnd) ,.

Figure..
4.16

• Winupper
Purpose..
Converts the characters in a string to uppercase.
Selected Presentation Manager Functions 665.

Prototype..
SHORT APIENTRY Winupper
(HLne hab,
USHORT idcp,
USHORT idcc,
PSZ psz) ,.

Figure..
7.20

• WinwindowFromlD
/
Purpose..
Returns the handle belonging to a child window.

Prototype..
HWND APIENTRY WinwindowFromlD
(HEED hwndparent ,
USHORT id) ,.

Figure..
4.5
667.

his appendix provides an alphabetical summary of the

.T predefinedPresentationManagermessagesthathavebeen
described in this book. The synopsis of each message gives
a brief statement of the purpose of the message and a ref-
erencetothefigureinthebookthatfullydescribesthemessageandthe
parametersthataccompanyit.Notethatthesemessagesfallintooneof
two general categories. The first category consists of messages that are
typicallysentfoaclientordialogwindowproceduretonotify.itofuser
input or other significant events. The second category comprises mes-
sages that are normally sent by a window procedure to windows man-
aged by the system, to control the behavior of these windows or to
obtain services from the system. The messages in the second category
effectively extend the Presentation Manager API accessed through sys-
tern function calls.
The messages summarized here are also listed in the inside covers of
the book, where each message is categorized according to the type of
information it provides or the service it performs. Note that these func-
tions form a subset of the full collection of predefined Presentation
Manager messages; see the technical documentation cited in the Bibli-
ography for information on messages not discussed in this book. See
also the section on Using Messages in Chapter 12 for a description of
programmer-defined messages.

• EM SETTEXTLIMIT
Purpose..
Sent to an edit control of a dialog box to set the maximum
number of characters that can be entered into the control.

Figure..
8.24

• LM DELETEALL
Purpose..
Sent to a list box control window to delete all items in the
list box.
•668 Programmer's Guide to the OS/2 Presentation Manager

Figure..
8.31

• LM_INSERTITEM
Purpose..
Sent to a list box control window to cause it to add an item to
the list.

Figure..
8.32

• LM_QUERYSELECTION
Purpose..
Sent to a list box control window to obtain the index of the
currently selected item.

Figure..
8.28

• LM_QUERYITEMTEXT
Purpose..
Sent to a list box control window to obtain the text for a
specific item within the list box.

Figure..
8.29

• MM_SETITEMATTR
Purpose..
Sent to a menu window to set the attributes of a menu item.

Figure..
7.9
Selected Presentation Manager Messages 669.

• MM _SETITEMTEXT
Purpose..
Sent to a menu control window to specify the text displayed
for a given menu item.

Figure..
7.10

• SBM_SETPOS
Purpose..
Sent to a horizontal or vertical scroll bar window to cause it
to set the position of the scroll bar slider.

Figure..
4.17

• SBM_SETSCROLLBAR
Purpose..
Sent to a horizontal or vertical scroll bar window to cause it
to set the range and position of the scroll bar slider.

Figure..
4.9

• WM __CHAR
Purpose..
Sentbythesystemtothefocuswindow(oractivewindow,if
there is no focus window) to notify it of a keyboard event
(that is, a key pressed or released).

Figure..
6.1
•670 Programmer's Guide to the OS/2 Presentation Manager

• WM_CLOSE
Purpose..
Sent by the system to the client window when the user
selects the Close item from the system menu.

Figure..
12.10

• WM_COMMAND
Purpose..
Sentbyacontrolwindowtoitsownertoreportasignificant
event.

Figure..
7.11

• WM_CONTROL
Puxpose..
Sentbyacontrolwindowtoitsownertoreportasignificant
event.

Figure..
8.18

• WM_CREATE
Purpose..
Sent by the system to a window when it is first created. It al-
lows the window procedure to perform initializations.

Figure..
3.16
Selected Presentation Manager Messages 671.

• WM DESTROY
__

Purpose..
Sent by the system to a window when it is about to be
destroyed.

Figure..
10.11

• WM ERASEBACKGROUND
Purpose..
Sent to the client window so that the client window proce-
dure can either erase the window itself, or have the system
erase the window using the default background color
(CLR BACKGROUND).

Figure..
11.15

• WM HSCROLL
__

Purpose..
Sentbyahorizontalscrollbarwindowtoitsownertoreport
relevant scroll bar events.

Figure..
4.12

• WM INITDLG
Puxpose..
Sent by the system to a dialog window when it is first
created, before it becomes visible.

Figure..
8.19
•672 Programmer's Guide to the OS/2 Presentation Manager

• WM INITMENU
Purpose..
Sent by the system to the client window when a menu item
is about to become active.

Figure..
7.7

• WM_MOUSEMOVE
Purpose..
Sentbythesystemtothewindowbeneaththemousepointer
(ortothemousecapturewindow,if any)eachtimetheposi-
tion of the mouse pointer changes.

Figure..
11.5

• WM PAINT
Purpose..
Sent by the system to a window whenever the entire win-
dow, or any portion of it, needs redrawing.

Figure..
2.19

® WM_QUIT
Purpose..
Posted to the message queue to terminate the application.

Figure..
2.10
Selected Presentation Manager Messages 673.

• WM SETFOCUS
Purpose..
Sent by the system to a window whenever it is about to
receive or lose the input focus.

Figure..
5.1

• WM SIZE
Purpose..
Sent by the system to a window whenever its size changes.

Figure..
3.23

• WM VSCROLL
Purpose..
Sent by a vertical scroll bar window to its owner to report
relevant scroll bar events.

Figure..
4.18
•674

• Bibliography

CORTES1, D. The Programmer's Essential OS|2 Handbook. Red-


wood City, CA: M & T Books, 1988.
DURANT, D., CARLSON, G., and YAO, P. Progr#777777er's G%£.de fo
Wz.7tdozus. Alameda, CA: SYBEX,1987.

HARBISON, S., and STEELE, G. C.. A Rc/crc77cc M¢7?I/¢J.


Englewood Cliffs, NJ: Prentice~Hall,1987.
IACOBUCCI, E. OS/2 Progr¢772771er's G#{.dc. Berkeley, CA:
Osbome/MCGraw-Hill, 1988.
Inte_i: 80286 and 80287 Programmer's Ref erence Manual. Saw+a
Clara, CA: Intel,1987.
Ir\t=1. 8P286 Operating Systems Writer's Guide. SaLr\+a ClanaL, CA..
Intel,1986.

KERNIGHAN, 8., and RITCHIE, D. Tfee C Progr¢77i77%.7ig L¢7i-


g#flgc. Englewood Cliffs, NJ: Prentice-Hall,1978.
LETWIN, G. J7is{.dc OS/2. Redmond, WA: Microsoft Press,1988.

Mic_ro?oft.O.pe_r.a_tingSystem/2,PresentationManagerReference.
Redmond, WA: Microsoft Corporation,1988.
M:ie_ro,soft. Op_era.ting System/2 Programmer's Tloolhit , Progranmer's
Re/ere71cc. Redmond, WA: Microsoft Corporation, 1988.
Mic:osg£:. Operating System/2 Software Development Kit, Presenta~
tion Manager Specification, Vol. I & 11. Tledrrrond, WA.. Mi.crosoft
Corporation,1987.
Mic_ro??£tLW!ndows. S_of_tware D evelopment Kit , Application Style
Gt4z.dc. Redmond, WA: Microsoft Corporation, 1987.

M:YFRS, B._, ar\d DONER, C. Graphics programming under win~


dozus. Alameda, CA: SYBEX,1988.

PFTZ0if:D_,. S. Pr_ogramming the os/2 Presentation Manager. Red-


mond, WA: Microsoft Press, 1988.
675.

ROBBINS, I. £sse71f£.¢J OS/2. Alameda, CA: SYBEX,1988.

STRAUSS, E. J7isl.de #ie 80286. New York, NY: Prentice-Hall,1986.

Sysfc77is Jot/r71¢J (magazine). Redmond, WA: Microsoft


Corporation.
YOUNG, MICHAEL I. MS-DOS Adt7fl7iced Progr¢#iffli.7tg.
Alameda, CA: SYBEX, 1988.

YOUNG, MICHAEL I. Progr¢fflffler's G%i.de fo OS/2. Alameda,


CA: SYBEX, 1988.

YOUNG, MICHAEL I. Sysfe7#s Progr¢77i77i€.ttg i.71 Tttrbo C.


Alameda, CA: SYBEX, 1988.
Index 677 .

• Index

formats for, 486487


.A
interface to, 479485
accelerators (keyboard), 43--44, 263, opering, 466468, 474
301-335 clipboard viewer window, 487L488
creating, 301-310 colors (for windows), 69-70,
managing, 311-322 509-510
anchor block handle, 28, 30-32 COMMANDMSG (OS/2 macro),
API (application program interface) 320
general,14-15,16-18 compatibility box, 4, 6
Presentation Manager, 24-25 control flags (keyboard), 235
automatic data segment, 92, 94 Control Panel (of Presentation
Manager), 20-21
.a control windows, 3849
Copy command, 479, 483
Backspace key, 252-259
Courier (font),114-117
bitmaps, 486487, 512-526
Ctrl-click (mouse), 581
Ctrl-drag (mouse), 581
.C current graphics position, 574-576
/c (compiler flag), 72 cursor,199-224
cache presentation space. See creating, 200-208
maintaining, 208-213
presentation space
character code (keyboard), 231 moving, 213-224
CHARMSG (macro), 228-229 Cut command, 479, 483
child window, 38, 4749
class. See window class .D
Clear command, 479, 483
default push button, 346
chck (mouse button), 579-580
Del key (Delete), 256, 262
chent window, 36, 4647
descriptor (segment), 7-11
chpboard, 461489
descriptor table, 7-11
accessing data in, 473478
desktop window, 41, 356
adding data to, 461473
device context, 65, 67
advanced features of, 485-489
dialog box editor, 338-343, 510-511
closing, 472473, 478
• 678 Programmer'sGuidetotheos/2Presentation
Manager

dialog boxes, 337457 Filing System (of Presentation


creating, 337-356 Manager), 21
managing, 356-395 Find command, 362-371
dialog frame, 346 Find Next command, 371-372
dialog procedure, 354, 356-359 focus window,150-151, 212-213,
Dos functions,16-18 228
DosAllocseg, 462-464, 589, 631 fonts (managing),114-122
DoscreateThread, 584-585, frame window, 3849
588-589, 631-632
DosExit, 590, 592, 632
.G
DosGetResource, 530-531, 632
DosGetseg, 476-478, 632-633 /G2 (compiler flag), 72
Dossemclear, 595, 597, 633 /Gs (compiler flag), 73
Dossemset, 595-596, 633 /GW (compiler flag), 73
Dossemwait, 595, 597ndoo, 605, global descriptor table,10
633-634 Go to Line command, 372-375
Dossizeseg, 532-533, 634 GpicharstringAt,128,130-133,
double-click (mouse button), 267, 634
579-581 GpicreateLogFont,126-128, 635
drag (mouse), 579-581 GpiDeleteBitmap, 519, 523-524,
dynamic-link libraries,11-16 635
dynamic linking,11-16 GpiErase, 509-510, 635-636
GpiLine, 574, 576-577, 636
GpiLoadBitmap, 519-521, 636
.E
GpiLoadFonts,114,117, 636-637
EM_SETTEXTLIMIT, 376-380, 667 GpiMove, 574-575, 577, 637
Enter key, 249-252 GpiQueryFonts,115-120, 637
errors GpisetBackcolor, 267, 480, 482, 638
handling,101-113 GpisetBackMix, 267, 480481, 638
return codes for,104 Gpisetcharset,126,129, 638-639
exit, 333 Gpisetcolor,128,131, 639
EXPORTS (linker definition file
command), 74
.H
handles, 74-75
.F
header files (OS/2), 27-28, 81-82
features of Presentation Manager, heap, managing, 83-101
18-25
Index 679 .

LM_QUERYITEMTEXT, 389-390,
HEAPSIZE (1inker definition file
668
command), 74, 94
hot spot (mouse pointer), 512, 541 LM_QUERYSELECTION, 389, 668
local descriptor table,10

.I
.M
icon editor, 498-500, 512-513, 519
icons, 41, 45, 491-512
macros (provided by OS/2), 84-89
designing, 498-500 MAKE (utility), 72
displaying, 502-512 menu command, 484
installing, 500-502 menu mnemonic, 484
identifier. See window identifier menus, 301-335
creating, 301-310
import library,11-12
managing, 311-322
include files. See header files
initializing (Presentation Manager), message-based architecture, 56-57
28, 30-33 message queue, 33-34
Ins key (Insert), 262-264 messages
insert mode, 333-334 for interprocess communication,
606-609
insertion point, 199
interprocess communication, 6-7, getting and dispatching, 49-57
594T609. See ¢Jso multitasking, processing, 58-60
semaphores, threads sending,158-160, 215

invalid areas (of windows), 62-65, metafile, 486487


70,168,171,180 MM SETITEMATTR (message),
315-317, 668
MM SETITEMTEXT (message),
.K 317-318, 669
kemel applications, 22-23 module definition file. See linker
keyboard, 227-298 definition file
keyboard accelerators. Scc mouse, 535-581
accelerators creating an interface for, 578-581
finding pointer location, 535-546
reading the buttons, 563-578
.L
setting pointer shape, 547-563
linker definition file, 73-74 MS-DOS applications, 22
linking,11-16, 73
multitasking, 6-7, 583-609
LM DELETEALL, 391, 394, 667-668
LM INSERTITEM, 391, 395, 668
•680 Programmer's Guide to the OS/2 Presentation Manager

.N relocation record,11-12
NAME (hnker definition ffle repeat count (keyboard), 232
command), 73 resource compiler, 302-304
New command, 322-330 resource script, 302-309
resources (OS/2), 301-302, 491-533.
See ¢Jso accelerators, bitmaps,
.0 dialog boxes, icons, menus,
object windows, 606, 608 programmer-defined
Open command, 380-395 resources, strings
overwrite mode, 333-334 Return key. See Enter key
owner (of a window),109,112

.S
.P Save As command, 375-380
parent window, 38, 47L49 Save command, 330-333
Pascal conventions, 31-33 scan code (keyboard), 231
Paste command, 479, 483 screen groups, 3-6
point (mouse), 579 scroll bars,147-197
pointer (mouse), 512 selection (of data)
presentation space, 65-69,115,118 described, 479
privilege levels,10-11 marking, 480483
Program Starter, 20 selector (segment), 7-11
programmer-defined resources, semaphores, 594-605
529-533 session manager, 5-6
proportionally spaced characters, sessions, 3-6
114-115 SBM_SETPOS (message), 173-174,
protected-mode screen groups, 4-6 669
protection fault,10 SBM_SETSCROLLBAR (message),
PROTMODE (1inker definition file 158,161, 669
command), 74 Shift-click (mouse), 580-581
Shift-drag (mouse), 580
•Q stack (for new threads), 588-589
STACKSIZE (linker definition file
queue. See message queue, system command), 74, 94
queue standard window, 3849
strings (stored as resources),
.R 526-529
real mode screen group, 4, 6 styles. Scc window styles
system queue, 227-228
Index 681 .

Wincreatestdwindow, 3849, 147,


.I 309, 642-643
tab characters, 268 Wincreatewindow, 606, 608ndo9,
Tab key, 248-249 643
Task Manager, 19-20 WinDefDlgproc, 357-358, 643nd44
threads (program), 584-609 WinDefwindowproc, 59, 62, 644
communicating between, WinDestroycursor, 207-208, 644
594-609 WinDestroyHeap, 96-97, 601,
starting, 585-593 644-645
see czZso interprocess WinDestroyMsgQueue, 58-59, 645
communication, multitasking, WinDestroypointer, 502, 505-507,
semaphores 512, 551, 560, 573, 645
title (window), 39, 4647 WinDestroywindow, 57-58,
645-646
.U WinDismissDlg, 356-357, 359, 646
WinDispatchMsg, 49, 51-57, 545,
user interface shell (of Presentation
583, 646
Manager),18-21
WinDlgBox, 354-357, 360, 646-647
window class, 34-39, 46-47
.V window identifiers,153,155-156
VI.o functions,16-17, 24-25 window procedure, 34, 37, 54-57
virtual-key codes,180, 214, 231-234 window styles, 34-38, 4146
virtual keys, processing, 259-264 windows, creating, 3849
virtual memory, 7-11 WinDrawBitmap, 519, 522-526, 647
WinDrawpointer, 502, 504, 507,
647-648
.W
WinDrawText, 69-71, 508-509, 648
AV2 (compiler flag), 72 WinEmptyclipbrd, 475476,
WinAlarm, 246-247, 256, 538-539, 648-649
599, 639 WinEnablewindow, 42,159,162,
WinAllocMem, 97, 99, 640 369, 649
WinBeginpaint, 65nd9,180, 640 WinEndpaint, 65, 67-68, 649
Wincloseclipbrd, 472473, 478, WinFillRect, 69-70, 649-650
640-641 WinFreeMem,101-103, 650
Wincreatecursor, 200-207, WinGetKeystate, 564-565, 650
211-212, 217-218, 224, 641 WinGetLastError,102,105, 651
WincreateHeap, 92-96, 641nd42 WinGetMsg, 49-53, 57, 583, 603,
WincreateMsgQueue, 33-34, 642 651
•682 Programmer's Guide to the OS/2 Presentation Manager

WinGetps,115,118, 266, 574, WinsetclipbrdData, 468471, 661


651-652 WinsetFocus,150-151, 661-662
Winlnitialize, 28, 30-33, 652 Winsetpointer, 512, 547-548,
WinlnvalidateRect, 209-211, 652 550-551, 560-561, 574, 662
WinLoadpointer, 502-503, 505-506, Winsetpointerpos, 554, 662
512, 550-551, 573, 653 Winsetsysvalue, 567
WinLoadstring, 528-529, 653 WinsetwindowText, 327-328, 663
WinLockHeap, 96, 98, 653-654 Winshowcursor, 207, 223-224, 663
WinMapwindowpoints, 537-538, Winshowpointer, 552-553, 663-664
544, 554, 654 WinTerminate, 58, 60, 664
WinMessageBox,107,110-112, Winupdatewindow,171-173, 664
323-324, 600, 654-655 Winupper, 328, 330, 664-665
Winopenclipbrd, 466468, 474, 655 WinwindowFromlD,153, 310, 665
WinpostMsg,159, 603-604, 655 WM_BUTTONI DOWN (mouse
WinQueryclipbrdData, 474475, message), 566, 574
655-656 WM_CHAR (message),179-180,
WinQueryFocus, 212-213, 656 227-236, 669
WinQueryMsgpos, 537, 541, 543, WM_CLOSE (message), 601-603,
545, 656 670
WinQuerypointerpos, 537, 542, 657 WM_COMMAND (message),
WinQuerysyspointer, 502, 318-320, 382, 388, 670
547-549, 560, 657 WM_CONTROL (message),
WinQuerysysvalue, 535-541, 368-369, 388-391, 670
563-564, 567, 657-658 WM_CREATE (message),114-115,
WinQuerywindow,153-155, 658 151-155, 200, 670
WinQuerywindowRect, 68, WM_DESTROY (message), 506, 671
524-525, 658 WM_ERASEBACKGROUND,
WinQuerywindowText, 367-369, 561-563, 578, 671
658-659 WM_HELP (message), 320-322
WinRegisterclass, 34-38, 659 WM_HSCROLL (message),
WinReleaseps,122, 266, 575, 659 163-174, 671
Winscrollwindow,168-173, 223, WM_INITDLG (message), 357,
660 370-371, 391-395, 671
WinsendDlgltemMsg, 379, 381, WM_INI"ENU (message),
660-661 311-318, 672
WinsendMsg,158-160,179, 605, WM_MOUSEMOVE (message),
661 545-546, 551-552, 574, 672
Winsetcapture, 545
Index 683 .

WM PAINT (message), 42, 49, 52,


59, 6ind5, 124-133, 200, 672
WM_QUIT (message), 53-54, 57,
602-603, 672
WM SETFOCUS (message),
200-202, 368, 673
WM SIZE (message),123-124,
155-162, 200, 673
WM VSCROLL (message),
174-179, 673

.Z
/Zp (compiler flag), 72
Selections from
The SYBEX Library
revised to include the latest features of
DOS MS-DOS Version 3.3. Two reference
books jn one, this title has separate sec-
tions for programmer and user. Multi-DOS
The ABC's of DOS 4 partitons, 31/2disk format, batch file call
Alan R. Miller and return feature, and comprehensive
coverage of MS-DOS commands are
250pp. Bef. 583-2
included.
This step-by-step introduction to using
DOS 4 is written especially for beginners.
MS-DOS Power user's Guide,
Filled with simple examples, The ABC's of
DOS 4 covers .the basics of hardware,
Volume I
software, disks, the system editor EDLIN, (Second Edition)
DOS commands, and more. Jonathan Kamjn
482pp. Ref. 473-9
ABC's of MS-DOS A fully revised, expanded edition of our
(Second Edition) best-selling guide to high-performance
Alan R. Miller DOS techniques and utiljtjes--with details
233pp. Bef. 493-3 on Version 3.3. Configuration, I/0, direc-
tory structures, hard disks, F]AM disks,
This handy guide to MS-DOS is all many
batch file programming, the ANsl.SYS
PC users need to manage their computer
device driver, more.
files, organize floppy and hard disks, use
EDLIN, and keep their computers orga-
nized. Additional information is given
MS-DOS Power User's Guide,
about utilities like Sidekick, and there is a Volume 11
DOS command and program summary. Martin Waterhouse/Jonathan Kamin
The second edition is fully updated for 418pp, Bef. 411-9
Version 3.3. A second volume of high-performance
techniques and utilities, with expanded
Mastering DOS coverage of DOS 3.3, and new material
(Second Edition) on video modes, Token-Ping and PC Net-
Judd Robbins work support, micro-mainframe links,
700pp. Ref. 555-7
extended and expanded memory, multi-
"The most useful DOS book." This seven- tasking systems, and more.

part, in-depth tutorial addresses the DOS User's Desktop Companion


needs of users at all levels. Topics range
from running applications, to managing Judd Robbins
files and directories, con figuring the sys- 969 pp. Bef. 505-0 Softcover
tern, batch file programming, and tech- 459-3 Hardcover
niques for system developers. This comprehensive reference covers
DOS commands, batch files, memory
MS-DOS Handbook enhancements, printing, communications
(Third Edition) and more information on optimizing each
user's DOS environment. Written with
Richard AIIen King
step-by-step instructions and plenty of
362pp. Bef. 492-5
examples, this volume covers all versions
This classic has been fully expanded and through 3.3.
Programmer's Guide to OS/2
MS-DOS Advanced
Programming Michael J. Young
625pp. Bef , 464-X
Michael J. Young
This concise introduction gives a com-
490pp. Bet. 578-6
plete overview of program development
Practical techniques for maximizing perfor-
under OS/2, with careful attention to new
mance in MS-DOS software by making tools and features. Topics include MS-
best use of system resources. Topics DOS compatibility, device drivers, serv-
include functions, interrupts, devices, multi- ices, graphics, windows, the LAN
tasking, memory residency and more, with manager, and more.
examples in C and assembler.
Programmer's Guide to GEM
Essential PC-DOS
Phillip Balma/William Fitler
(Second Edition) 504pp. Bef. 297-3
Myril Clement Shaw/
GEM programming from the ground up,
Susan Soltis Shaw
including the Besource Construction Set,
332pp. Bef. 413-5 lcoN Editor, and Virtual Device Interface.
An authoritative guide to PC-DOS, includ- Build a complete graphics application
ing version 3.2. Designed to make experts with objects, events, menus, windows,
out of beginners, it explores everything alerts and dialogs.
f rom disk management to batch file
programming. Includes an 85-page Understanding Hard Disk
command summary. Management
The IBM PC-DOS Handbook Jonathan Kamin
500pp. Bef. 561-i
(Third Edition)
Put your work, your office or your entire
Richard AIlen King
business literally at your fingertips, in a cus-
359pp. Bet. 512-3
tomized, automated MS-DOS work environ-
A guide to the inner workings of PC-DOS ment. Topics include RAM disks, extended
3.2, for intermediate to advanced users and expanded memory, and more.
and programmers of the IBM PC series.
Topics include disk, screen and port con- Programmer's Guide to
trol, batch files, networks, compatibility, Windows
and more.
(Second Edition)
David Durant/Geta Carlson/Paul Yao
704pp. Bef. 496-8
The first edition of this programmer's
OTHER OPERATING
guide was hailed as a classic. This new
SYSTEMS AND edition covers Windows 2 and Windows/
386 in depth. Special emphasis is given to
ENVIRONMENTS over fifty new routines to the Windows
interface, and to preparation for OS/2
Presentation Manager compatibility.
Essential OS/2
Judd Robbins Graphics Programming Under
367pp. Bef. 478-X Windows
This introduction to OS/2 for new and pro- Brian Myers/Chris Doner
spective users offers clear explanations of
646pp. Bet. 448-8
multitasking, details key OS/2 commands
Straightforward discussion, abundant
and functions, and updates current DOS
examples, and a concise reference guide
users to the new OS/2 world. Details are
to graphics commands make this book a
also given for users to run existing DOS
must for Windows programmers. Topics
programs under OS/2.
range from how Windows works to pro-
valuable for students and programmers
gramming for business, animation, CAD, alike.
and desktop publishing. For Version 2.

Programming the 68000


Steve Williams
539pp. Bef.133-0
This tutorial introduction to assembly-
ASSEMBl:y language programming covers the com-
plete 68000 architecture and instruction
LANGUAGE set, as well as advanced topics such as
interrupts, I/0 programming, and interfac-
ing with high-level languages.
Programmjng the 8086/8088
James W. Coffron Programming the 6809
311pp. Bef.120-9 f}odnay Zaks/William Labiak
A concise introduction to assembly- 362pp. Bef. 078-4
language programming for 8086/8088-
A step-by-step course in assembly-
based systems, including the IBM PC.
language programming for 6809-based
Topics include architecture, memory organi-
home computers. Covers hardware orga-
zation, the complete instruction set, inter-
nization, the instruction set, addressing,
rupts, I/0, and IBM PC BIOS routines.
I/0, data structures, program develop-
ment and complete sample applications.
Programming the 80286
C. Vieillefond Programming the 6502
487pp. Ref. 277-9 F]odnay Zaks
ln-depth treatment of assembly-level pro- 408pp. Bef.135-7
gramming for the IBM PC/AT's 80286 The best-selling, step-by-step course in
processor. Topics include system archi- assembly-language programming for the
tecture, memory management, address
6502 chip used in Apple, Atari and Com-
modes, multitasking and more; plus a
modore computers. From basic concepts
complete reference guide to the jnstruc-
to architecture, instruction set, address-
tion set.
ing, I/0, sample applications and more.

Programming the 80386 Programming the Z80


John H. Crawford/
(Third Edition)
Patrick P. Gelsinger
F]odnay Zaks
775pp. Bef. 381-3
624pp. Bef. 069-5
A detailed tour of the 80386 for assembly-
A self-teaching guide to assembly-language
language programmers. Topics include
registers, data types and instruction programming for the wide range of Z80-
based microcomputers. Includes the
classes, memory management, protec-
Z80 architecture and instruction set,
tion models, multitasking, interrupts, the
addressing, I/0 techniques and devices,
numerics coprocessor, and more.
data structures and sample programs.
DOS Assembly Language
Z80 Applications
Programmjng
James W. Coffron
Alan R. Miller
295pp. Bef. 094-6
365pp. Bef. 487-9
A handbook for assembly-language
This book covers PC-DOS through 3.3
programmers on the principles of Z80
and gives clear explanations of how to hardware operations. Topics include
assemble, link, and debug 8086, 8088, using BOM, static and dynamic HAM,I/0,
80286, and 80386 programs. The interrupts, serial communication and
example assembly language routines are several specific Lsl peripheral devices.
list processing, database operations,
LANGUAGES BIOS-level support, program develop-
ment, expert systems, natural language
processing, and much more.
Mastering Turbo Pascal 5
Douglas Hergert Introduction to Turbo Prolog
595pp. Bet. 529-8 Carl Townsend
This in-depth treatment of Turbo Pascal 315pp. Bet. 359-7
Versions 4 and 5 offers separate sections This comprehensive tutorlal includes sam-
on the Turbo environment, the new
ple applications for expert systems, natu-
debugger, the extensive capabilities of the
ral language interfaces, and simulation.
language itself, and special techniques
Covers every aspect of Prolog: facts,
for graphics, date arithmetic, and recur-
objects and predicates, rules, recursion,
sion. Assumes some programming
databases, and much more.
knowledge.
Turbo Pascal Toolbox
Advanced Techniques
in Turbo Pascal (Second Edition)
Frank Dutton
Charles C. Edwards
425pp. Bet. 602-2
309pp. Bet. 350-3
This collection of tested, efficient Turbo
This collection of system-oriented tech-
Pascal building blocks gives a boost to
niques and sample programs shows how to
intermediate-level programmers, while
make the most of IBM PC capabilities using
teaching effective programming by
Turbo Pascal. Topics include screens, win-
example. Topics include accessing DOS,
dows, directory management, the mouse menus, bit maps, screen handling, and
interface, and communications.
much more.

Turbo BASIC Instant Reference Introduction to Pascal:


SYBEX Prompter Series Including Turbo Pascal
Douglas Hergert
(Second Edition)
393pp. Bet. 485-2
Rodnay Zaks
This quick reference for programmers
464pp. F3ef. 533-6
offers concise, alphabetical entries on
This best-selling tutorial builds complete
every command--statement, metastate-
mastery of Pascal--from basic structured
ment, function, and operation--in the
Turbo BASIC language with descriptions, programming concepts, to advanced I/0,
data structures, file operations, sets,
syntax, and examples cross-referenced to
related commands. pointers and lists, and more. Both lso
Standard and Turbo Pascal.
Introduction to Turbo BASIC
Introduction to Pascal
Douglas Hergert
(Including UCSD Pascal)
523pp. Bet. 441-0
F`odnay Zaks
A complete tutorial and guide to this now
420pp. Bef. 066-0
highly professional language: Turbo
This edition of our best-selling tutorial on
BASIC, including important Turbo extras
such as parameter passing, structured Pascal programming gives special atten-
loops, long integers, recursion, and 8087 tion to the UCSD Pascal implementation
compatibility for high-speed numerical for small computers. Covers everything
operation. f rom basic concepts to advanced data
structures and more.
Advanced Techniques
in Turbo Prolog Celestial BASIC: Astronomy on
Your Computer
Carl Townsend
398pp. Bet. 428-3
Erie Burgess
300pp. Bef . 087-3
A goldmine of techniques and predicates
for control procedures, string operations, A complete home planetarium. This col-
lection of BASIC programs for astronomi-
validation, display and storage. Focuses
cal calculations enables armchair
on creating and manipulating custom log-
astronomers to observe and identify on
ical data types: dates, dollars, phone
screen the configurations and motions of
numbers, much more.
sun, moon, planets and stars.

Mastering Turbo C
Stan Kelly-Bootle
COMMUNICATIONS
578pp. Bef. 462-3
No prior knowledge of C or structured pro-
gramming is required for this introductory Mastering Crosstalk XVI
course on the Turbo C language and devel- Peter W. Gofton
opment environment by this well-known 187pp. Bef. 388-0
author. A logical progression of tutorials and Becoup the cost of this book in a matter of
useful sample programs build a thorough hours with ready-made routines that
understanding of Turbo C. speed up and automate your on-line data-
base sessions. Tutorials cover every
Systems Programming jn Turbo C aspect of installing, running and customiz-
Michael J. Young ing Crosstalk Xvl.
365pp. Bef. 467-4
An introduction to advanced program-
ming with Borland's Turbo C, and a gold-
mine of ready-made routines for the
system programmer's library: DOS and
HARDWARE
BIOS interfacing, interrupt handling, win-
dows, graphics, expanded memory, The RS-232 Solution
UNIX utilities, and more.
Joe Campbell
194pp. Bef.140-3
Understanding C
A complete how-to guide to trouble-free
Bruce H. Hunter RS-232-C inter facing from scratch. In-
320pp. Bet.123-3 depth coverage of concepts, techniques
A programmer's introduction to C, with and testing devices, and case studies
special attention to implementations for deriving cables for a variety of common
microcomputers--both CP/M and MS- computers, printers and modems.
DOS. Topics include data types, storage
management, pointers, random I/0, func- Mastering Serial
tion libraries, compilers and more. Communications
Peter W. Gofton
Mastering C
289pp. Bef,180-2
Craig Bolon
The software side of communications,
437pp. Bet. 326-0
with details on the IBM PC's serial pro-
This in-depth guide stresses planning,
gramming, the XMODEM and Kermit
testing, efficiency and portabHjty in C
protocols, non-ASCII data transfer,
applications. Topics include data types, interrupt-level programming and more.
storage classes, arrays, pointers, data Sample programs in C, assembly lan-
structures, control statements, I/0 and the
guage and BASIC.
C function library.
Microprocessor lnterfacing
Data Handling Utilities Techniques (Third Edition)
in Microsoft C
Austin Lesea/Rodnay Zaks
Pobert A. Radcliffe/Thomas J. Raab 456pp. Bef. 029-6
519pp. Bef. 444-5
This handbook is for engineers and hob-
A C library for commercial programmers, byists alike, covering every aspect of
with techniques and utilities for data entry, interfacing microprocessors with periph-
eral devices. Topics include assembling a Programmer's Guide
CPU, basic I/0, analog circuitry, and bus to the Amiga
standards. Robert A. Peck
352pp. Bet. 310-4
From Chips to Systems: An A programmer's hands-on tour through
Introduction to Microcomputers the Amiga system--AmigaDOS, Exec,
(Second Edition) Graphics, Intuition, Devices, Sound, Ani-
Rodnay Zaks/Alexander Wolfe mation, and more--packed with in-depth
580pp. Bet . 377-5 information and sample programs (in
The best-selling introduction to microcom-
Amiga C) showing proper use of system
routines.
puter hardware-now fully updated, revised,
and illustrated. Such recent advances as 32-
bit processors and RISC architecture ate
introduced and explalned for the first time in
a beginning text. SPREADSHEETS AND
Mastering Digital Device Control INTEGRATED
William a. Houghton
366pp. Bet . 346-5
SOFTWARE
Complete principles of system design
using single-chip microcontrollers, with The ABC's of 1-2-3
numerous examples. Topics include (Second Edition)
expanding memory and I/0, interfacing Chris Gilbert/Laurie Williams
with multi-chip CPUs, clocks, display
245pp. Bef. 355-4
devices, analog measurements, and
0n/i.ne Toddy recommends it as "an easy
much more.
and comfortable way to get started with
the program." An essential tutorial for
novices, it will remain on your desk as a
HOME COMPUTERS valuable source of ongoing reference and
support. For Belease 2.
Amiga Programmer's Handbook,
Mastering 1-2-3
Volume I (Second Edition)
(Second Edition)
Eugene P. Mortimore
Carolyn Jorgensen
624pp. Bet. 367-8
702pp. Bef. 528-X
The complete reference for Amiga graph-
Get the most from 1-2-3 Belease 2 with
ics programming. System commands
this step-by-step guide emphasizing
and function calls are presented in detail,
advanced. features and practical uses.
organized by funcitonal class: Exec,
Topics include data sharing, macros,
Graphics, Animation, Layers, Intuition
spreadsheet security, expanded memory,
and the Workbench. Includes AmigaDOS
and graphics enhancements.
version 1.2.

Amiga Programmer's Handbook, Lotus 1-2-3 Desktop Companion


Volume 11 (SYBEX Ready Reference Series)
Eugene P. Mortimore Greg Harvey
976pp. Bef. 501-8
365pp. Bef. 384-8
A full-time consultant, right on your desk.
ln-depth discussion of Amiga device I/0
Hundreds of self-contained entries cover
programming--including programming
every 1-2-3 feature, organized by topic,
with sound and speech--with complete
indexed and cross-referenced, and sup-
details on the twelve Amiga devices and
their associated commands and function plemented by tips, macros and working
examples. For Release 2.
calls. Inclues AmigaDOS version 1.2.
Advanced Techniques and placed in context with prior versions
in Lotus 1-2-3 so that both new and previous users will
Peter Antoniak/E. Michael Lunsford benefit from Cobb's insights.
367pp. Bef. 556-5
This guide for experienced users focuses on The ABC's of Quattro
advanced functions, and techniques for Alan Simpson/Douglas J. Wolf
designing menu-driven applications using 286pp. Bef. 560-3
macros and the Belease 2 command Especially for users new to spreadsheets,
language. Interfacing techniques and this is an introduction to the basic con-
add-on products are also considered. cepts and a guide to instant productivity
through editing and using spreadsheet
Lotus 1-2-3 Tips and Tricks formulas and functions. Includes how to
Gene Weisskopf print out graphs and data for presenta-
396pp. Bet. 454-2 tjon. For Quattro 1.i.
A rare collection of timesavers and tricks
for longtime Lotus users. Topics include Mastering Quattro
macros, range names, spreadsheet Alan Simpson
design, hardware considerations, DOS 576pp. Bef. 514-X
pperations, efficient data analysis, print- This tutorial covers not only all of Quat-
ing, data interchange, applications devel- tro's classic spreadsheet features, but
opment, and more. also its added capabilities including
extended graphing, modifiable menus,
Lotus 1-2-3 Instant Reference and the macro debugging environment.
SYBEX Prompter Series Sjmpson brings out how to use all of Quat-
Greg Harvey/Kay Yarborough Nelson tro's new-generation-spreadsheet capa-
296pp. F]ef. 475-5; 4 3/4x8 bilities.

Organized information at a glance. When


Mastering Framework 11
you don't have time to hunt through hun-
dreds of pages of manuals, turn here for a Douglas Hergert/Jonathan Kamin
quick reminder: the right key sequence, a 509pp. Bef. 390-2
brief explanation of a command, or the This business-minded tutorial includes a
correct syntax for a specialized function. complete introduction to idea processing,
"frames," and software integration, along
Mastering Lotus HAL with its comprehensive treatment of word
Mary V. Campbell processing, spreadsheet, and database
342pp. F3ef. 422-4 management with Framework.
A complete guide to using HAL "natural
language" requests to communicate with The ABC's of Excel
1-2-3-for new and experienced users. on the IBM PC
Covers all the basics, plus advanced HAL Douglas Hergert
features such as worksheet linking and
326pp. Bef. 567-0
auditing, macro recording, and more.
This book is a brisk and friendly introduc-
tion to the most important features of
Mastering Symphony
Microsoft Excel for PC's. This beginner's
(Fourth Edition) book discusses worksheets, charts, data-
Douglas Cobb base operations, and macros, all with
857pp. Bef. 494-1 hands-on examples. Written for all ver-
Thoroughly revised to cover all aspects of sions through Version 2.
the major upgrade of Symphony Version
2, this Fourth Edition of Doug Cobb's Mastering Excel on the IBM PC
classic is still "the Symphony bible" to this Carl Townsend
complex but even more powerful pack- 628pp. Bef. 403-8
age. All the new features are discussed A complete Excel handbook with step-by-
iskette Off er
.,D
Companion Diskette Set
The Co777p¢71!.oro Di.skcffc Scf provides all program listings given in this
book,plusalladditionalfilesneededtopreparetheexampleprograms.Thetwo
diskettes will enable you to make immediate use of these files for testing or
modifying the example programs, or for developing your own Presentation
Manager applications.

PNIEdit
PM/£dl.f is a full-featured version of the text editor presented in this book,
which will allow you to write programs and other text files within a window of
the Presentation Manager. It provides the following features: an online help
facility, plus complete documentation in a ready-to-print file; cut, paste, and
other block operations; search and replace commands; background compiling
or printing of listings; macros; an undo command; word processing facilities;
and many other features.

OS/TooZs, Version 1.1


0S/TooZs, version 1.1, is a set of software tools designed to facilitate writing
OS/2 kernel and Presentation Manager applications. This tool set includes the
following basic components (a complete description will be sent on request):

• A set of dynamic-link library functions, which extend the os/2 Apl and
the standard C library. Functions are provided for both kernel and
Presentation Manager programs.
A set of programmer's utilities for OS/2 and the Presentation Manager,
including programs for designing text mode screens and windows, for
writing and executing macros, for cutting and pasting data between
screen groups, and for saving text and graphics screens in files, plus a
GREP program and other utilities.
• Source code: Complete, commented source code is provided for all func-
tions and utilities.
• Documentation: Thorough documentation for all utilities and functions
is supplied in a ready-to-print file.

ORDERFORM
Copies of the Companion Diskette Set @ $29.50 each

Copies of PM/£dz.£ @ $49.50 each


Copies of OS/TooJs (version 1.1) @ $49.50 each

California residents: add 6% sales tax


Shipping and Handling: add $2.50 ($5.00 for UPS COD or
foreign orders)

Total Order
NameAddres City/State/ZipAlldisket esarmentpayabletcards;forforeiYoursoftware

e in standard 51/4-inch IBM format. Please send a check for full pay-oMichaelJ.YoungorrequestUPSCOD(nopurchaseordersorbankgnorders,pleasesendaninternationalmoneyorderinU.S.dollars).wil beshippedimmediately.Orderfrom:

Michael J. Young
P.O. Box 5068
Mill Valley, CA 94942
415/383-5354

S]YBF¥isnotaffiliatedwithMichaelJ.Youngandassumesnoresponsibilityforanydefectin
the disk or program.
TO JOIN THE SYBEX MAILING LIST OP OBDEB BOOKS
PLEASE COMPLETE THIS FOF"

_ COMPANY

I PLEASE MAIL ME MOBE INFOBMATION ABOUT SYBEX TITLES

SHIPPING AND HANDLING PLEASE ADD $2.00


OPIDEP FOF" (There is no obligation to order)
PEP BOOK VIA UPS

FOF3 OVERSEAS SuRFACE ADD $5.25 PER


PLEASE SEND ME TllE FOLLOWING:
BOOK PLUS $4.40 F3EGISTF]ATION FEE

QTY PRICE :%%?VpELBSsES?4S4Ao'B¥£!:TARDAP,8JNBF2E5EPER

CALIFORNIA F]ESIDENTS PLEASE ADD


APPLICABLE SALES TAX

TOTALAMOuNTPAYABLE

DCHECKENCLOSED DVISA
I MASTEF}CARD I AMEF3lcAN EXPRESS
ACCOUNT NUMBEF3

TOTAL BOOK OBDEB ~ S~ EXPIB.DATE ~ DAYTIMEPHONE

CUSTOMEB SIGNATUBE

OTHEP COMPUTEPI TITLES YOU WOULD LIKE


CHECK ABEA OF COMPUTEP INTEPEST:
TO SEE IN PPINT:
I BUSINESS SOFTWABE

I TECHNICAL PBOGBAMMING

I OTHEB:

OCCUPATION
THE FACTOB THAT WAS MOST IMPOPTANT IN
YOUF} SELECTION: I PF30GRAMMER I TEACHEF3

I THE SYBEX NAME I SENIOB EXECUTIVE I HOMEMAKEB

I QUALITY ECOMPUTEF3CONSULTANT ERETIRED

I PBICE I SUPEF3VISOR I STUDENT

I EXTRA FEATUF]ES I MIDDLE MANAGEMENT I OTHEB:

I COMPREHENSIVENESS I ENGINEEB/TECHNICAL

I CLEAB WBITING I CLEBICAL/SEBVICE

I OTHEF3 I BUSINESS OWNER/SELF EMPLOYED


CHECK YOUF] LEVEL OF COMPUTEFI USE
OTHEP COMMENTS:
I NEW TO COMPUTERS

I INFF}EQUENT COMPUTER USEF]

I FF]EQUENT USER OF ONE SOFTWAF]E

PACKAGE:

NAME

I FREQUENT USER OF MANY SOFTWARE

PACKAGES

I PROFESSIONAL PROGF3AMMER

PLEASE FOLD, SEAL, AND MAIL TO SYBEX

T|
SYBEX, INC.
2021 CHALLENGEF] DR. #100
ALAMEDA, CALIFOF}NIA USA

94501

e. SEAL
SYBEX Computer Books
are different.
Here is why . . .
At SYBEX, each book is designed with you in mind. Every manuscript is
carefully selected and supervised by our editors, who are themselves
computer experts. We publish the best authors, whose technical expertise
is matched by an ability to write clearly and to communicate effectively,
Programs are thoroughly tested for accuracy by our technical staff. Our
computerized production department goes to great lengths to make
sure that each book is well-designed.

In the pursuit of timeliness, SYBEX has achieved many publishing firsts.


SYBEX was among the first to integrate personal computers used by
authors and staff into the publishing process. SYBEX was the first to
publish books on the CP/M operating system, microprocessor interfacing
techniques, word processing, and many more topics.

Expertise in computers and dedication to the highest quality product


have made SYBEX a world leader in computer book publishing. Trans-
Iated into fourteen languages, SYBEX books have helped millions of
people around the world to get the most from their computers. We hope
we have helped you, too.

For a complete catalog of our publicaGie±±i


SYBEX, lnc. 2021 Challenger Drive, #100, Alameda, CA 94501
Tel: (415) 523-8233/(800) 227-2346 Telex: 336311
Fax: (415) 523-2373
Segments • RESOURCE
DosAllocseg MANAGEMENT
DosGetseg
Dossizeseg
General
DosGetResource 10.26

Bitmaps
• MESSAGE GpiLoadBitmap
MANAGEMENT WinDrawBitmap
GpiDeleteBitmap
Message Processing
WinGetMsg Icons and Pointers
WinDispatchMsg WinLoadpointer 10.8
WinDefwindowproc WinDrawpointer 10.9
WinDefDlgproc Winsetpointer 11.6
WinDestroypointer 10.10
Message Queues
WincreateMsgQueue Strings
WinDestroyMsgcfueue WinLoadstring 10.25

Sending Messages
WinsendMsg
WinsendDlgltemMsg
• THREAD
WinpostMsg MANAGEMENT
DoscreateThread
DosExit
• MOUSE
MANAGEMENT
Buttons
• WINDOW
WinGetKeystate
MANAGEMENT
11.16
(scc ¢Jso Control Window Management)
Pointer Shape
WinQuerysyspointer Creation/Destruction
Winsetpointer Wincreatestdwindow
Wincreatewindow
PositionIvisibilityofpbinter WinDestroywindow
WinQuerypointerpos 11.2 WM CREATE
WinQueryMsgpos 11.3 WM INITDLG
Winsetpointerpos 11.11 WM CLOSE
Winshowpointer 11.10 WM_QUIT
WM MOUSEMOVE 11.5 WM DESTROY
Focus Window Miscellaneous
WinQueryFocus WinEnablewindow
WinsetFocus WinlnvalidateRect
WinMapwindowpoints
Information WinsetwindowText
WinQuerywindow Winupdatewindow
WinQuerywindowRect WinwindowFromlD
WinQuerywindowText WM SIZE

:,.-..,.--.

:',;
PROGRAMMER'S GUIDE
T0 THE

PRESEN"TI0N MANAGER
Programmer's Guide to the OS/2 Presentation Manager is a tutorial
Praise for Michael J. Young's
introduction to programming for the Presentation Manager, covering all
MS-DOS Adranced ltogranmingr
you need to know to develop complete, full-featured applications for "A good choice for C and
OS/2's graphic programming interface. It requires no previous
assembly language
experience with either Presentation Manager or Microsoft Windows
programmers...wen written to
programming, but offers a clear, systematic approach to learning and show how to optinrize your
using the essential features of this vast, complex, and often confusing
System.
programs.''
Computer Book Review
Bufld a complete Presentation Manager appHcation, from the ground
up. Part I uses a hands-on programming project-writing a Presentation
Manager text editor-to introduce the basic architecture and essential
features of any Presentation Manager application. Turn here to learn
how to:
• open and write text to an on-screen window
• use memory-management functions to buffer text
• add scrou bars, and scroll data in the program window
• create, display, and manage a cursor
About the Author
• implement a full keyboard interface
Michael J. Young is a software
• design and install menus and accelerator keys engineering consultant and a developer
of programmer's tools and uthities for
• design, manage, and display dialog boxes MS-DOS and OS/2. He is a member
of the ANSI committee on the
standardization of the C language,
Tap the rystem's advanced features to enhance your software. Part 11
and the author of MS-DOS 4dva!#ced
explores a selection of advanced topics, including:
Pro_gra.mmpg,SyFtemsprogramming
in T_u!bo C, Bind Programwier's Guidre
• inter facing with the clipboard fo OS/2, all from SYBEX. He
• defining and using resources: icons, pointers, bitmaps, strings, graduated from Stan ford University,
and currently lives and works in Miu
and programmer-defined types Vaney, Cahifornia.
• adding a mouse interface
• using graphics functions
• using and synchronizing multiple threads of execution

Appendices include a glossary, a summary of operating-system services


and predefined messages, and a bibliography.

I COMPUTER B00KSHELFCATEGORY |
L OPERATING SYSTEMS: OS/2 ISBN 0-Bt]5aa-5Ei-7 U.S.$26.95

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy