═══ 1. Jan 1996 Title Page ═══ The Electronic Developer's Magazine for OS/2 Portions copyright (c) by IQPac Inc. Volume 4, issue 1 Administrivia Well, here I am again, and I'm going to do what I did last month - concatenate the "From the Editor" sections together, liberally sprinkle the key, and serve them up again as though fresh from the oven. However, you should read this month's title page, if you didn't last month, because you might miss some interesting things here that aren't anywhere else... Gearing Up for Games Update I received mail from Michael Duffy regarding the Gearing Up for Games series. Because he now works for Stardock Systems, he is working quite a lot up to 18 hours a day, trying to meet Christmas deadlines and such. However, he said he does have the code done for the next part of the series and simply needs to finish the text. Look for this to appear in February or soon after. Missing in Action I still haven't located Johan Wikman, however. He was writing the RMX-OS2 series, which I personally found quite interesting. Mail to him bounces and I have no other way of contacting him. If you do, please do and let me know how to contact him also. Best Wishes for a Speedy Recovery I hope that our student readers did well on their finals, especially Carsten. He has suffered from a lack of time lately, which is why all of the typos slipped through the cracks on the December articles. I apologize for this, but English was never my best subject. Credit Where Credit is Due Before I begin this week's spew of talk, I would like to publicly thank Rocco Caputo for the immense and intense amount of help he provided to me last month on the Perl script that processes the new Search facility on the web site. comp.os.os2.announce , Etc. Eh? New Search facility? If you haven't been keeping in touch with the net over the holidays, EDM/2 has announced (by the time you read this) a permanent home for the web version of the publication. (Actually, the home belongs to IQPac Inc. but who's counting?) The new URL of the magazine is http://www.iqpac.com. There are a lot of things that are different there from what you were used to at the venus site. You might check out the press release that was posted to the various newsgroups. If you've noticed, I've been trying harder to keep the community abreast of things via the newsgroups comp.os.os2.announce and comp.os.os2.programmer.*. My aim is to achieve the level of feedback that Trevor Smith (from OS/2 e-Zine!) provides in comp.os.os2.misc, but it will be difficult. In order to continue taking EDM/2 (and, to an extent, IQPac, Inc.) to higher levels, it is necessary to generate and maintain a high interest level for the magazine. The point of this is that, although this is the preferred place for you to watch, you can also keep an eye out in the OS/2 newsgroups for the same and possibly additional information about EDM/2. More Thanks to be Spread This is where I would like to thank Rajv (as he is known in the #os/2 channel on IRC) for allowing EDM/2 to spend so much time at venus on his hardware. Without him, the web site would have "crashed and burned." Fortunately, there are always people out there who want to help out when help is sorely needed. Another Call for Writers Unfailingly, I get a letter or two every month from people asking if topic such-and-such would be interesting. Let me put this in a way everyone could understand: Yes! (Eesh!) Seriously, if you have a topic that is relevant to OS/2 development, we want you to write about it! Read the Article Submission Guidelines first and then start your keyboards! Holiday Wishes Although I am aware of the many religions that span our reader base, I would like to wish everyone a happy holiday. Ah, how I love the holidays. There isn't anything like lots of good music, food, and fellowship to brighten the days during the end of December. You can keep the messes and the dirty dishes. Anyway, my family decided to brave the winter cold in New York by coming up (from South Carolina!) to spend this week with my wife and I. It's been fun, and has kept us busy. Sockets Speaking of busy, I've managed to talk to a couple of people despite the arrival of my family. It seems that we all got the same idea and decided to write a socket library to help us develop our TCP/IP applications. Of course, I did not think to ask whether they were planning to release the library to the general public. I would certainly hope so, however. Myself, if my library ever matured to the point where it was generic enough to be usable from a variety of applications, I would release it. Of course, the ultimate goal for me is to fold the socket library into the Common/2 communications subsystem. The current implementation uses named pipes, but it would be nice to allow the application to use the same interface for both named pipes and sockets. Managers and Such Of course, such an approach is not without its design difficulties. Although named pipes are supported natively by OS/2, sockets are not, and the DLL's needed by TCP/IP may or may not be there. This immediately suggests either a bunch of DosLoadModule() and DosQueryProcAddr() calls by Common/2 (referred to as dynamic binding) or a set of statically bound DLL's which are called by Common/2. However, now I have to add error checking to insure that the application doesn't specify a protocol that isn't installed, etc. As I said, this approach isn't without its difficulties. No More PC Week, Infoworld, etc. It's funny how I tout the web as the greatest thing since sliced bread, yet I find that I am at a loss, now that I no longer will be able to browse the printed versions of the weekly trade publications that I used to read. I guess I will now have to make an extra effort to set aside time at home to keep up-to-date on the goings-on in the world. Does this mean the web will never entirely replace the printed publication? Well, I don't think any of us were naive enough to believe this in the first place. (Remember the "paperless office"?) However, I do think that industry analysts overestimate the worth of the web, from the user's point of view. I guess that, until ISDN and other forms of high speed, digital communication capabilities become available and more popular, the status quo will rule. Watch, though, for the day when it changes, because I believe it will change quickly. New Books 'Ever wanted to write a book? Although OS/2 seems to be catching up to Windows in terms of the number of books it has available, it still has quite a long way to go. If you think you have the ability and the time and the desire to stay committed to completing a tome, then you should see what you can do to get a publisher to sponsor you. This thought arose because it seems that I've started receiving more and more notes that begin with: "since you have made the rounds in book publishing..." ═══ 2. Copyright Notice ═══ Copyright Notice EDM/2 is published by IQPac Inc. IQPac Inc. can be reached via U.S. Mail at the following address: IQPac Inc. 7 East Broadway, Box 804 New York, NY 10038 U.S.A. Editor-in-chief Larry Salomon Jr. (larry_salomon@iqpac.com) Associate editor Carsten Whimster (carsten_whimster@iqpac.com) Contributing editor Gordon Zeglinski (gordon_zeglinski@iqpac.com) CEO/President Larry Salomon Jr. (larry_salomon@iqpac.com) All material is copyrighted by its original author. No part of this magazine may be reproduced without permission from the original author. This publication may be freely distributed in electronic form provided that all parts are present in their original unmodified form. A reasonable fee may be charged for the physical act of distribution; no fee may be charged for the publication itself. Neither IQPac Inc. nor this publication are affiliated with International Business Machines Corporation. OS/2 is a registered trademark of International Business Machines Corporation. Other trademarks are property of their respective owners. Any mention of a product in this publication does not constitute an endorsement or affiliation unless specifically stated in the text. The OS/2 Accredited Logo is a trademark of International Business Machines Corporation and is used by IQPac Inc. under license. This On-line Publication is independently produced by IQPac Inc. and IBM is not responsible in any way for its contents. IQPac Inc. is an accredited member of the IBM Independent Vendor League. Copyright Notice - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 3. How Do I Get EDM/2? ═══ How Do I Get EDM/2? EDM/2 can be obtained in any of the following ways: Anonymous FTP on the Internet hobbes.nmsu.edu in the /os2/newsltr directory. ftp.luth.se in the /pub/os2/programming/newsletter directory. Elsewhere on the Internet generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. The EDM/2 mailing list. Send an empty message to edm2-info@knex.mind.org to receive a file containing (among other things) instructions for subscribing to EDM/2. On Compuserve All back issues are available in the forum OS2DF2, section 15. On BBS's From BBS's in Denmark, send email to Jesper Nielsen at afdata@pop02.ny.us.ibm.net for a location near you. How do I Get EDM/2? - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 4. Plugging Into OS/2 Socket Programming (Part 3) ═══ ═══ 4.1. Introduction ═══ Plugging Into OS/2 Socket Programming (Part 3) Written by Edward Boykin Introduction Welcome to my third article on OS/2 socket programming. We are finally going to look at a more advanced client-server setup. This month, I will discuss only the client part and treat the server only as a 'black box' so that you may concentrate on one half of the set up. I have included only the client source and executables, but in order to make the client usable I wrote it so it would work with an internet "chat" type server (not IRC) that already exists. The server to be connected with is hard-coded in the client source. Next month I will update the client so you can connect to the server I am writing. For some of you who have been unable to work with sockets because of the cost of the IBM TCP/IP toolkit, I have some good news: it has come to my attention that the Warp Connect CD-ROM contains all the headers, libraries and DLLs of the toolkit; however, it does not contain documentation. If you own this CD then do a search for the "toolkit" directory and you will find this zip file there. (Those of you who do not have Warp Connect are still out of luck, unfortunately.) On to the show... Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 4.2. The Select() Function ═══ The Select() Function In my study of socket programming, I found that only one function really ever confused me and that was the select() function. There are two versions of select() in the OS/2 socket SDK: one version is the same as the BSD socket call which uses bitmasks and such to set up the function; the other is IBM's version of the function with the same name. I found the former to be too difficult to use so I opted to use the latter instead. The select() function is used to check one or many socket descriptors for readability, writability, and exceptions. The function looks like this: int select ( int *socks, int noreads, int nowrites, int noexcept, int timeout ); Figure 1) IBM's version of the select() function. The first parameter is an array which contains the socket descriptors you wish to perform the select call on. When creating this array, place all of the sockets you wish to check for readability first, then for writability, and finally for exceptions. So, you could theoretically have an array of three integers with the same integer, or socket descriptor, in all three places, meaning that you want to see if you can read from and write to the socket and check for any socket exceptions. The next three parameters tell select how many sockets in that array are for reading, writing and exception checking. The final parameter is a timeout value. This value is in seconds and determines how long the select call will block if none of the sockets check out. If you make this value 0 select will not block, and if you make it -1 select will not timeout. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 4.3. The Anatomy of a Client ═══ The Anatomy of a Client The client I have provided for this article is a very simple, PM based TCP packet client. In a nutshell, it connects to a server and sends and receives packet to and from the server. The server allows multiple client connections and when one client sends a message the server relays that message to all of the other connected clients. This is what allows the network "chatting" to take place. A good client application should have at least the following capabilities. Of course, it needs to be able to send and receive messages quickly with these message being of some standardized protocol. It should also be able to connect to any server which supports the particular chat protocol. (This ability will be available in the next article.) The client should have an easy to use user interface. And, finally, the client should be easily enhanced. The User Interface I mentioned before that the client was to be PM based. I did this to make it easier to handle user input and server output. The interface for the sample client is a simple one. It contains two buttons, a read-only multiple line editor, and an entry field. One button is for connecting to the server and the other for disconnecting while the MLE is for server output and the entry field is for user input. It is a crude, but effective, interface for our needs. A more advanced client interface might allow for drag-n-drop font changes or dynamic font changing based on the dimensions of the main window, etc. These things, however, are for the future. The Packet Protocol The packet protocol I have selected is one which is used by the "Internet Citizens Band", or ICB, servers for years. A single packet to or from the client contains three parts and has the form: "l p m", where l is a single byte which specifies the total length of the packet including itself, p is the packet type indicator, and m is the packet data. The current client only supports the login packet, a, and the open message packet, b, for the packet type. Even though we have a limited number of packet types right now, by including this byte of information we are not limited to just these packet types - the "Internet Citizens Band" server actually supports many other packet types. I have limited this client only for simplicity's sake. The single byte of the length does pose one restriction, however, and that is that the total length of message can only be 253 bytes since the length byte includes the protocol type and itself in that length. Sending Packets Sending packets is very simple. I have defined a user message called SM_SEND which, when sent to the send/receive thread, tells the thread that there is an outgoing message. The message contains a pointer to the already prepared packet in mp1. Receiving Packets Receiving packets is accomplished in almost the same way as sending them. When the send/receive thread loop receives a packet, it is broken down by removing the l (size) and p (packet type) from the string and then runs through a case statement to determine the packet type. Since the client only supports the b (open message) packet type, this is the only case we look for. We also define a default which takes any of the other packets from the server and ignores them. Once it is determined that a complete open message packet has been received the thread then sends another user message, SM_RECV, to the user interface thread. Once again mp1 contains a pointer to the message string. Enhancing the Client It should be obvious how the client is easily enhanced in the last few sections. I have used a packet protocol which allows for a byte to specify a different kind of packet. This could include private messages, specially formatted open messages, or just about anything else you can think of. We could create a broken up message which could be any packet type that was over 253 bytes. The packet could then be broken into 253 byte chunks and sent separately. The possibilities are almost endless here. Imagination is the only limit. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 4.4. The Operation of CLIENT.EXE ═══ The Operation of CLIENT.EXE Now that I have described what goes into the client program I will begin to put it all together. As I said before, the client contains two threads. I will call this the user interface thread and the send/receive thread. The user interface thread handles the user input and server output and the connection of the client to the server. The send/receive thread handles the sending and receiving of message packets to and from the server. The two threads will talk to each other via user defined messages. Take a look at Figure 2. I have diagrammed the basic execution layout of the client program there. I will start with the top of the diagram in the user interface thread and work may way over. Figure 2) Execution path of client. Initializing the Client Application Upon initial client startup the main window is displayed. You must supply a nickname on the command line when you start CLIENT.EXE. At this point the user should press the "Connect" button. The connect button send a WM_COMMAND message with the button id, ID_CONNECT, as one of its parameters which the window procedure handles by calling a function setupSockets(). SetupSockets() will initialize the socket environment and create the socket that the client will use to communicate with the server. If this all occurs normally then setupSockets() will return the socket descriptor that was created. If all does not go well then it will return 0 or a negative number. If it is a negative number then this is the error code multiplied by -1. Assuming we had a good socket returned then WinPostMsg() is used to send a SM_SOCKETGO message. The basic structure is in the code to add some kind of error notification to the user but for times sake I did not include anything to that effect. Connecting to the Server The SM_SOCKETGO message is used to tell the client that the socket environment is all set up ready to go and we need to connect to the server now. The message will be handles by calling the connectToServer() function. We send to this function our socket descriptor, the server name, and the server port. I have defined, in client.h, the server to be icb.sjsu.edu and the port to be 7326. Leave these be until next month when I will have the server ready for you. ConnectToServer() does just that - it connects to the server. It sets up the necessary hostent struct which is used by the socket function connect() to determine the place we want to connect to. Notice we are using the gethostbyname() function in order to determine icb.sjsu.edu's interment IP address. Upon a successful connection the function loginToServer() is called. The parameters to this function are the socket descriptor and your chosen nickname. LoginToServer() gives us our first look at sending and receiving a message packet. This is the only time that message will be sent or received outside of the send/receive thread. The comments at the beginning of the function describe the format of the login packet. Notice that fields are separated by a ^A or \001 character. This is part of the standard message packet protocol so if you were to create some new message packet type that used fields you would want to use that character to separate them. If you follow through the first couple lines of actual code you will see how I go about assembling the message packet for our login. The first communication activity that takes place is the reception of the protocol packet from the server. This is the server saying "hi there". Using a bit of string and pointer acrobatics, I take the two fields of this packet and create the connect message to be displayed on the MLE. The last thing to do is to send that login packet that was put together. If all goes well the function will return TRUE; else it will return FALSE to the caller, the connectToServer() function. A TRUE return code will cause a SM_CONNECTED message to be posted; otherwise the message "Unable to Connect to Server" is displayed on the MLE. The SM_CONNECTED message tells the client that all is ready for normal communications with the server. The message is handled by calling _beginthread() to start up the send/receive thread. The Send/Receive Thread Loop We now come to the meat of the client application. It is here that all further communication between the client and the server will take place. The thread basically executes an continual loop until either we shut down or the server shuts us down. This loop has two sections:  Check message loop for outgoing messages. If there are some, then call select() to check for writeability of socket Continue until all messages are sent or select() returns a not ready.  Check socket for readability by letting select() run for a few seconds before returning. Process any incoming messages and pass them on by using SM_RECV messages. The fist part of the loop checks for incoming SM_SEND, or SM_KILL messages. This is pretty self explanatory. If an SM_SEND message is received then the first message parameter, mp1, is used as the pointer to the message to be sent. Select() will be called to check the socket for writeability. If the socket is ready to have data sent out then all that is needed is to call the send() function. The packet is contained in a chunk of allocated memory pointed to by the SM_SEND message's mp1 parameter. Some error checking should be used here to insure that all the bytes were sent. The last step is to free the allocated memory which contains the packet. This process will continue until no more messages are in the queue. The SM_KILL message can also be received. The user defined message is used to tell the send/receive thread to shutdown the socket connection and end the thread. To do this soclose() is called and the Connected variable is set to FALSE. If there are no messages to read or once all of the messages have been read and processed and no SM_KILL messages were received then the socket will be checked for incoming packets from the server. To do this, select() is called again. I included a timeout value of 5 seconds just to give the receive section a chance to get some data in if there is none at the moment. If select() returns a ready socket then the first byte is read to determine the length of the incoming packet. Another read is then done to read in just that amount of data specified in the first byte. After checking to be sure we got the correct amount of data in, the packet type is checked in a switch() statement. If the packet type is b, open message, then the packet message is sent to the user interface thread via the SM_RECV thread. If a packet type is received which is not supported then the memory that contains it is freed. This loop continues indefinitely until the SM_KILL is received or the program is terminated. The User Interface Thread The user interface thread, as I said before, is responsible for handling the user input and server output. The whole thread runs off of a standard client window procedure. The user input part is fairly simple. The message loop captured the WM_CHAR message and looks for the enter or return key to have been pressed. It then queries the text in the WND_INPUT window and if there is text in there it processes the string. To process the string, the string, open message packet type, and packet length byte is inserted into a 256 byte character string. A null terminator is added to specify the end of the created string. The message packet is then sent to the send/receive thread via the SM_SEND message. The final thing done is to show the user his own message on the output window. The server output is handled a bit differently. Once the SM_RECV message is received another series of string acrobatics is done to break the fields of the packet up. When we receive an open message packet from the server it contains 2 fields. The first field is the nickname of who sent the message and the seconds is the message itself. Once the packet is broken up it is then displayed on the output window. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 4.5. Wrap Up and Next Time ═══ Wrap Up and Next Time Well, we are almost finished. This month I have use a simple client application which allows a chat over TCP/IP networks. Please examine the code and try to understand how I have integrated the socket functions into a PM program and how things like the select() call work. If you have any questions I can always be reached at aviator@mindspring.com. Next time I will include a server which you can set up yourself and allow anyone on your network to chat. I will also change the client code so you can specify what server you want to use. Thanks for you time. I hope you have learned a lot. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5. /dev/EDM/BookReview ═══ ═══ 5.1. Introduction ═══ /dev/EDM2/BookReview Written by Carsten Whimster Introduction In /dev/EDM2/BookReview, I focus on development books and materials. I have written this column from the point of view of an intermediate PM C programmer and intermediate REXX programmer. Pick up whichever book strikes your fancy, and join the growing group of people following our PM programming columns. I have already reviewed a number of beginner's books, and will try to concentrate a bit more on intermediate techniques and special topics from now on. Please send me your comments and thoughts so that I can make this column what you want it to be. I read and respond to all mail. OS/2 Warp Presentation Manager API is a new reference book from Wiley which covers the Presentation Manager API (surprise), both documented and undocumented. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.2. Errata ═══ Errata My Web page now has a new section on publishers, including a list of currently available books from each publisher. If you have any comment, mail me. If you have any additions or corrections, mail me. Note the change of URL too. Check it out at http://www.undergrad.math.uwaterloo.ca/~bcrwhims/os2/index.html . I have been using my new copy of VAC++ and the WorkFrame is slow, even with C programs. I also don't seem to be able to turn off all the informational messages that a compile brings up. I have them turned off for the compiler itself, but the rest of them are as healthy as ever, completely cluttering up even a routine compile. Oh well, it works well enough I guess. I did run into some problems when I wanted a stand-alone program. I was using the math library, but in spite of an include, the linker could not find the library, and the compile would not consistently finish. Sometimes it would, but mostly it wouldn't. Eventually I just created a table of cos and sin values in my header file, but what a hazzle. Other than the speed, the message overdose, and the math compilation problems, it is a great environment, and I am taking to LPEX quicker than I thought I would. The speed, though, the speed. On a DX4-100 with 20Mb it really ought to fly, but no such luck. I hope they rewrite it in VAC++ rather than Smalltalk next time. I should be releasing a small utility soon, and perhaps write an article for EDM/2 on the problems I had to solve while coding. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.3. OS/2 Warp Presentation Manager API ═══ OS/2 Warp Presentation Manager API This month's book is second in a new series of three API references from John Wiley and Sons, covering the Control Program, Presentation Manager, and Workplace Shell APIs. This particular book also promises to cover more than just what the Warp Toolkit online references cover, while presenting the material in a well-structured, easy-to-use manner. Here are the chapters: 1. PM Application Setup and Cleanup 2. Registering and Creating Windows 3. Messaging 4. Keystrokes and Focus 5. Presentation Spaces and Device Contexts 6. Window Drawing Functions 7. Clipping and Invalid Regions 8. Menus 9. Dialogs 10. Standard Dialogs 11. Resources 12. Help 13. Window Information 14. System Information 15. Atoms 16. The Clipboard and Dynamic Data Exchange 17. Rectangles 18. Task List Functions 19. Workplace Shell Functions 20. National Language Support Appendix A. WinLockVisRegions Similar to last month's book, publishing deadlines did not allow the development of a full complement of examples for each API, but there are a few this time. The major difference between this book and last month's book is that I find the chapter introductions a little more sketchy. Perhaps that was necessary to keep the book a similar size, but I prefer slightly more detailed descriptions, and the PM Win functions really require this unless you have already used them. Like the previous book, the organization of the book is as follows:  each major topic is given its own chapter (see above)  each chapter has a few introductory paragraphs, tutorial in nature  each function which comes under this chapter's heading is then given, as follows: - name and type of API (ie. chapter heading repeated) - brief description - syntax - parameters, each with a brief explanation, and tables of possible values, if appropriate - returns, with value and description of error codes - other info, including include file, define, ordinal, and DLL API resides in - see also, with related APIs, each with a page number - notes, including warnings, restrictions and so on This very simple layout makes it very simple to navigate, and powerful, although having used this book for the better part of a month, I find that this layout does compromise the quick-lookup ability for a single function, which most other reference books have. I am undecided as to whether this layout is better in the end, or whether a more traditional pure-alphabetical layout is preferable. In writing my current program I think the alphabetical approach has won so far, but perhaps in the long run, the new layout works best? In any case, both work, and both have their strengths and weaknesses. One thing is for sure, I like the OTHER INFO section, with its INCLUDE information. Now my utility has only the necessary includes, and whether that makes a difference or not to the size of the compiled program or the compilation speed, I feel better about it. I have never liked the fact that all functions in a library get brought in by C, whether you need them or not. That is it, for the second time! I have been much busier this month, so I didn't get all the way through this book like last month. With this type of reference that really isn't necessary though. The functions are all there, and the first appendix even has a late-breaking addition of the WinLockVisRegions function. I am not sure why it is here, and not in the main part, since it is documented in the pmwin.h file, but perhaps it wasn't in previous versions and only just made it in time for publicat ion. This review is a little short again, but this month I won't include a sample function since it is so similar in layout to the original book in the series. I will instead just add a example of the sample code that is in a very few functions in this book. This one is for WinBeginPaint(), style unaltered: case WM_PAINT: { HPS hps; // cached-micro PS handle RECTL rcl; // bounding rectangle hps = WinBeginPaint ( hWnd, NULLHANDLE, &rcl ); GpiErase ( hps ); WinEndPaint ( hps ); } return 0; Figure 1) Sample code from the book for the WM_PAINT message. There you are, all done for this month. This book, due to the "not quite enough for me" chapter introductions, and the struggle with alphabetized versus sectionized layout, loses the A+ of the last book, but retains an A, and is still a great reference book. Another must-have from this series. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.4. Summary ═══ Summary This is now my favorite PM reference book, as well as one of my only two PM reference books [grin]. I had a less successful time with the sectionized layout than with the Control Program API book, perhaps because of the more diverse nature of the mater ial, and I needed more of an explanation at the start of each chapter, due to the more complicated nature of the material, but got only the same level of explanation, so it gets an A instead. Still a great book, and so far without much competition as a PM reference book in my library. A must-have for serious PM programmers. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.5. Book Reviewed ═══ Book Reviewed  OS/2 Warp Presentation Manager API, Barnum - John Wiley and Sons. ISBN 0-471-03887-3. US$29.99, CAN$40 - OS/2 C/C++ PM Programmers - A This is an excellent reference to the Presentation Manager API. It is very complete, but the topical layout may throw you for a loop if you are used to alphabetized books. It contains syntax, usage guides, data structures, and sample cross-referencing. Highly recommended. Notes Please note that books aimed at different audiences should only be compared with great care, if at all. I intend to concentrate on the strong points of the books I review, but I will point out any weaknesses in a constructive manner. Legend BOOK: The name of the book, and the author(s) PUBLISHING INFORMATION: Publishing company, ISBN, and approximate price. AUDIENCE: This is a description of the audience I think the book targets best. This is not intended as gospel, just a guideline for people not familiar with the book. MARK: My opinion of the success of the book's presentation, and how well it targets its audience. Technical content, accuracy, organization, readability, and quality of index all weigh heavily here, but the single most important item is how well the book covers what it says it covers. Many books try to cover too much, and get a lower mark as a result. A+ Ground-breaking, all-around outstanding book. A Excellent book. This is what I want to see happen a lot. A- Excellent book with minor flaws. B+ Very good book with minor flaws or omissions. B Good book with some flaws and omissions. B- Good book, but in need of improvement. C+ Mediocre book with some potential, but in need of some updating. C Mediocre book with some good sections, but badly in need of fixing. C- Mediocre book, little good material, desperately in need of an overhaul. D Don't buy this book unless you need it, and nothing else exists. F Don't buy this book. Period. COMMENTS: This is a very brief summary of the review proper. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.6. Content Index ═══ Content Index This Content Index is designed to let you find the book that covers the topics you need to learn about. It will eventually have a lot of categories, with each book being rated along each row. These tables will be quite large, and will continually grow, so please give me your feedback regarding what categories you would like to see, and which you don't. It may take me a while to flesh them out, so have a little patience. BOOK LEGEND ┌─────┬───────┬───────────────────────────────────────────────────────────────────┐ │Code │Issue │Title │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │RWP │2-3 │Real World Programming for OS/2 2.1 │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │LPE │2-4 │Learning to Program OS/2 2.0 Presentation Manager by Example │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │ODD │2-5 │Writing OS/2 2.1 Device Drivers in C │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │GPI │2-6 │OS/2 Presentation Manager GPI │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │TAO │2-7 │The Art of OS/2 2.1 C Programming │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │MOR │2-8 │Mastering OS/2 REXX │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │RSH │2-9 │REXX Reference Summary Handbook │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │ADO │2-10 │Application Development Using OS/2 REXX │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │PMP │2-11 │OS/2 Presentation Manager Programming │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │DOA │3-1 │Designing OS/2 Applications │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │OSP │3-2 │OS/2 Programming │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │TGO │3-4 │The GUI-OOUI War │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │OU │3-5 │OS/2 Warp Unleashed, Deluxe Edition │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │QR1 │3-6 │WIN Functions, OS/2 Quick Reference Library Volume 1 │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │PWG │3-7 │Programming the OS/2 Warp Version 3 GPI │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │DHP │3-8 │Designing High-Powered OS/2 Warp Applications │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │OCH │3-9 │OS/2 Certification Handbook │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │CPA │3-10 │OS/2 Warp Control Program API │ ├─────┼───────┼───────────────────────────────────────────────────────────────────┤ │PMA │4-1 │OS/2 Warp Presentation Manager API │ └─────┴───────┴───────────────────────────────────────────────────────────────────┘ NOTE: Books which cover the same material can look similar in this table, but be different in real life. The style of a book, for example, can not be seen from a quick table, so make sure that you follow up by reading the reviews of the books you find here. Finally, be sure that the books you are comparing are aimed at the same audiences. PM C BOOKS ┌─────┬─────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐ │BOOK │MARK │Kernel │Device │VIO and│PM │GPI │Fonts │Print │ │ │ │Basics │Driver │AVIO │Intro │ │ │ │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │RWP │B+ │2 │0 │0 │4 │4 │4 │3 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │PME │B- │1 │0 │0 │2 │2 │2 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │ODD │A │0 │5 │0 │0 │1 │0 │1 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │GPI │C+ │0 │0 │0 │0 │5 │2 │3 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │TAO │B+ │3 │2 │1 │4 │1 │2 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │PMP │A- │1 │0 │1 │5 │3 │4 │2 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │OSP │B+ │2 │0 │0 │3 │2 │1 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │QR1 │A │0 │0 │0 │(WIN) 5│0 │0 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │PWG │A- │0 │0 │0 │1 │5 │5 │5 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │CPA │A+ │5 │0 │0 │0 │0 │0 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │PMA │A │0 │0 │0 │5 │1 │1 │1 │ └─────┴─────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘ REXX BOOKS: ┌─────┬─────┬─────────┬─────────┬─────────┐ │BOOK │MARK │REXX │WPS │Reference│ │ │ │Intro │ │ │ ├─────┼─────┼─────────┼─────────┼─────────┤ │MOR │B │4 │0 │2 │ ├─────┼─────┼─────────┼─────────┼─────────┤ │RSH │A │1 │2 │5 │ ├─────┼─────┼─────────┼─────────┼─────────┤ │ADO │A- │3 │2 │4 │ └─────┴─────┴─────────┴─────────┴─────────┘ SYSTEM AND NON-PROGRAMMING BOOKS: ┌─────┬─────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┬───────┐ │BOOK │MARK │Kernel │Device │VIO and│PM │Thread │GPI │Fonts │Print │WPS │ │ │ │Basics │Driver │AVIO │ │ │ │ │ │ │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │DOA │A │4 │4 │2 │4 │5 │3 │2 │3 │0 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │TGO │B │0 │0 │0 │2 │1 │0 │2 │1 │5 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │OU │A+ │1 │4 │4 │5 │2 │5 │5 │5 │5 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │DHP │A │4 │4 │2 │4 │5 │3 │2 │3 │1 │ ├─────┼─────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┼───────┤ │OCH │A │? │? │? │? │? │? │? │? │? │ └─────┴─────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┴───────┘ RATINGS LEGEND: ┌─┬──────────────────────┐ │0│No coverage │ ├─┼──────────────────────┤ │1│Very light coverage │ ├─┼──────────────────────┤ │2│Introductory coverage │ ├─┼──────────────────────┤ │3│Good Coverage │ ├─┼──────────────────────┤ │4│In-depth coverage │ ├─┼──────────────────────┤ │5│Authoritative │ └─┴──────────────────────┘ /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 5.7. Coming Up ═══ Coming Up I will now take a break from this API series, both because I have a few other books lined up, and also because I have not done any WPS programming, and so need to get going on that before I can do a proper review of it. I will likely review Programming in REXX or The REXX Cookbook next month, or perhaps The OS/2 Warp Programmer's Sidekick, which I have found quite useful recently. Books I have:  OS/2 Warp Workplace Shell API, Pollack  The OS/2 Warp Programmer's Sidekick, Diviney and Murray  Programming in REXX, Daney  The REXX Cookbook, Callaway Other books I would like to review: The Design of OS/2, 2nd Edition, Kogan and Deitel - I am having trouble getting a copy of this, so if anyone can help, please do. A 1st edition would do me fine too. OS/2 C++ Class Library: Power GUI Programming with C-Set++, Law, Leong, Love and Tsuji - This is on the way I am told. OS/2 Presentation Manager GPI, 2nd edition, Winn - I really would like to review this soon, as I am coming across some stuff that the old one doesn't handle in an up-to-date manner, and want to see what the new one is all about. Visual Age: Concepts and Features, ? - This sounds interesting. If anyone has a book they want to see reviewed, I will be happy to oblige. Just mail me and tell me which. Publishers can send me books at the address on my personal page at the end of the magazine, and I will review all OS/2 development-related a nd advanced user books I receive. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 6. OOPS Avenue ═══ ═══ 6.1. Introduction ═══ OOPS Avenue Written by Gordon Zeglinski Introduction So what happened to the rest of the screen saver DTS series? Seems life is full of mini-disasters up here. Last month I injured my shoulder which made typing impossible. This month I had to reinstall OS/2 and reformat the hard disk. I have not yet reinstalled the SOM toolkit or Metaware's High C/C++. Until I have time to do so, the DTS articles will have to wait. Instead, we will talk this month about C++ exceptions. C++ exceptions are a powerful method of handling special cases. Traditionally, one might do something like: switch( foo(MyArguement,&var) ){ case 0: //alls well break; case 1: foo(0,&var); //myarguement is invalid.. break; case 2; //out of memory or other serious error exit(2); break; default: fprintf(stderr,"Unknown Error returned from foo\r\n"); break; } Figure 1) Traditional method of error code handling. Depending on the return value from foo(), an error condition may or may not exist. Exceptions follow a similar concept but are far more powerful. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 6.2. What is Exactly is a C++ Exception? ═══ What is Exactly is a C++ Exception? An exception is an object designed by the programmer specifically to relay error information. They can be organized in hierarchies, as in the following example: class ErrorBase{ public: ErrorBase(char *F,int L); ErrorBase(const ErrorBase &error); virtual ~ErrorBase(); const char* GetFile() const {return File;} int GetLine() const {return Line;} protected: char *File; int Line; }; class ErrorBadArg:public ErrorBase{ public: ErrorBadArg(char *F,int L); ErrorBadArg(const ErrorBadArg &error); ~ErrorBadArg(); }; class ErrorNoMem:public ErrorBase{ public: ErrorNoMem(char *F,int L); ErrorNoMem(const ErrorNoMem &error); ~ErrorNoMem(); }; Figure 2) Sample exception hierarchy. An advantage of using heirarchies of error objects is that any error object with a parent can be caught by blocks expecting the parent object. We'll look at catching exceptions by the exception object's parent class later. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 6.3. Try, Catch and Throw ═══ Try, Catch and Throw "Try" blocks are used to "catch" exceptions that are thrown in functions called within the block. We have already seen that an exception is nothing more than an object designed to convey error information. Unlike the simple switch case, however, try blocks can be nested within and across function calls. Also, exceptions don't rely on the function returning a value. The following sample code illustrates a nested exception. void foo1(){ try{ foo2(); } catch(ErrorBase error){ cerr<<"An exception was thrown from file "< class MemBlock{ typedef T *pT; public: MemBlock(size_t len){Block=new T[len];} ~MemBlock(){if(Block!=NULL) delete [] MemBlock;} operator pT(){return Block;} protected: pT Block; }; class MutexRequest{ typedef unsigned long ULONG; typedef unsigned long HMTX; public: MutexRequest(HMTX hand,ULONG time){hmtx=hand;DosRequestMutexSem(hmtx,time);} ~MutexRequest(){DosReleaseMutexSem(hmtx);} protected: HMTX hmtx; }; void foobar(char *arg){ MemBlock X(300); MutexRequest sem(hMux,-1); if(arg==NULL) throw ErrorBadArg; /* do other stuff here */ } Figure 9) Removing the leak by performing resource management in the constructor and destructor. This last approach has a hidden advantage. Suppose we called some other functions in foobar() and one of these functions threw an exception. What would happen in either of our first 2 versions of foobar()? The answer is that we would have the same resource leak that we fixed in the last 2 versions. Unless we add a try/catch block in foobar() and then place calls to DosReleaseMutexSem() and delete inside the catch block, we will leak resources. Encapsulating the resources and using constructors/destructors to handle their allocation and deallocation provides a safer alternative than manually maintaining the deallocation of resources in several possible exit points. The second pitfall is using exceptions too liberally. Suppose we have a function that has a fixed set of valid results. Let's say that one result happen most of the time, but it is possible in some cases for the others to occur. Should we use exceptions? The answer is no. Exceptions should only be used to indicate error conditions, not to indicate which action a function performed. As we seen from the C++ compiler benchmarks several issues ago, throwing exceptions is expensive. Not only is throwing the exception expensive, but setting up a try block alone can have noticeable overhead. To keep performance acceptable, exceptions should only be used to indicate an error condition. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 6.7. Wrapping Things Up ═══ Wrapping Things Up This concludes our look at C++ exception handling. We covered how to define exceptions, catching, and throwing exceptions. Also, we seen how to handle unexpected results by using the set_terminate() and set_unexpected() functions. Exceptions provide a formal method for handling and declaring error conditions. They have significant run time cost and should only be used where necessary. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7. REXX Inside and Out ═══ ═══ 7.1. Introduction ═══ Rexx Inside and Out Written by Joy Wyatt Introduction When Rexx was originally written for IBM's Virtual Machine operating system, it was given no native file handling capabilities. VM has its own file handling command, EXECIO, which has proven to be sufficient in that environment. There is a down side to everything and the problem with EXECIO is that it is part of VM and not an architected element of the Rexx language. When portability became an issue, Mike Cowlishaw, author of Rexx, went back to the drawing board and designed enhancements to the language that allow Rexx programs to read and write to files in such a way as to be independent of the operating platform. This article will take a look at each of Rexx's file handling functions to perform the basics of file manipulation. "So what, Uncle Bob, are the basics", you ask? Well, boys and girls, quit calling me Uncle Bob and we'll get on with it. Rudimentary file function includes opening a file, writing to it, reading from it, and closing it. There is more than one way to do each of these and we will discuss all of the ones I know about, their good points, and their bad. Before we get into the nitty gritty we must get a definition behind us. file pointer: A file pointer is a place holder the operating system uses to keep track of where the program is reading or writing in a file. Let's use a small file as an example to provide an illustrative definition. Imagine the file as 512 characters typed onto a page. Take your finger and point to the first character on the page. Read the character under your finger and move your finger to the next character. Your finger on the page is like the file pointer OS/2 uses. When you tell OS/2 to read a line or a character from a file, OS/2 moves its "finger" to the next line or character to be read. Although OS/2 doesn't really have any fingers it does have a better imagination than you do. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.2. Opening a file ═══ Opening a file While Rexx does not contain a specific "open file" function, there are at least five methods of opening a file on purpose (explicitly as opposed to implicitly). The first four are easy to explain away. Any attempt to write to an unopened file using the lineout or charout functions will implicitly attempt to open the file for read/write processing. These functions can also be used to explicitly open a file. The following statements: /* open file and place file pointer on line 1 */ rc = lineout( myFile, , 1 ); rc = charout( myFile, , 1); Figure 1) Implicitly opening a file for read/write access. will attempt to open the file whose name is contained in the variable myFile. If the open process is successful the value of rc will be "0" and the file pointer will be positioned at the beginning of the existing file. If, for some reason, the file cannot be opened rc's value will be "1". While this is functional, it generally leads to such descriptive error messages as, "Hey, Hoser! Your file just ain't going to make it this time." This isn't a lot of debug information to go on. The input functions are similar in that the first use of them on an unopened file will implicitly attempt to open the file. They also may be used for an explicit open as follows: /* open file and read zero lines from line 1 */ rc = linein( myFile, 1, 0 ); /* open file and read zero chars from char 1 */ rc = charin( myFile, 1, 0); Figure 2) Implicitly opening a file for read-only access. When either of these functions, used in this manner, are successful the file pointer is placed at the first character of the file. As far as diagnostic information is concerned these input functions are worse than their output siblings. These functions return data and no numeric code. If everything went well there is no return data from the function because of the "0" in the parameter list. If the file could not be opened then there is no return data from the function. This leads to error messages similar to, "Hey, Hoser. If you got this message then there were no syntax errors in the open call, but we don't know if your file opened successfully." "Alas!", you cry. "Are users of my Rexx code destined to be called 'Hosers' for the rest of their days?" Maybe. But you can at least give them some decent debugging information as well by using the stream function to open your files. The stream function is multipurpose and can handle the opening of files very nicely. Stream has other uses, but this article will not delve into them. We will limit ourselves to using stream to open and close files. The following invocation of stream: rc = stream( myFile, "c", "open" ); Figure 3) Explicitly opening a file. will attempt to open the file for reading and writing and place something a bit more usable in the return area if the attempt fails. Should the file be opened successfully the string "READY:" is stored in your result area. If there are problems, however, a string similar to "NOTREADY:nn" is issued. The "nn" in this case is a return code that indicates the reason the attempt to open the file failed. This code can be used with OS/2's help facility to provide the user with some valuable information. See example code Rexx_a.cmd for an illustration. The stream function can also be used to open a file and designate its intended use. This allows you to set the file pointer for the processing you desire. The default open mode is "read" which will place the file pointer at the first byte of the file. Changing the third parameter from "open" to "open write" will cause the file pointer to be placed at the end of the file. "Open read" as the third parameter will set the file pointer to the top of the file and limit the function to read only. Most of the Rexx programs that I have seen, though, do not use any of these explicit methods for opening a file for processing. If the two terms "quick and dirty" and "Rexx programming" seem synonymous to you then you may already be aware that the first use of any of the input/output functions will implicitly attempt to open the file. You still, of course, are limited to the eloquent "1" or "0" diagnostics with this method. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.3. Reading Data From a File ═══ Reading Data From a File Unlike open, you cannot read (or write) data by accident. Two built-in methods for reading data exist in the Rexx language. The "C" programmer in me was fairly comfortable dealing with the "one character at a time" functionality of the charin function, but the rich string handling functions in Rexx have caused me to all but abandon charin. Charin Charin reads one or more characters at a time from a specified location and returns the data to the result area. It is quite handy when there are no CR LF defined records in the file to be read or when a specified block length is needed, but that is usually a contrived situation on the PC platform. To test the performance, I created a file with 1024 records of 1024 bytes each and read them using both charin and linein. Detailed results are located in a table after the linein discussion. Syntax of the charin function: text = charin(myFile, start, count); Figure 4) Syntax of charin. To make things interesting none of the parameters are required. If myFile is not specified then the data is taken from the standard input device (usually the keyboard). The second parameter, start, positions the file pointer before the read takes place. The final parameter, count, specifies the number of characters that are to be read. So to read eight characters starting at the 50th character, the function would be coded as follows: text = charin(myFile, 50, 8); Figure 5) Using charin to read a specific set of characters in a file. That's about all there is to it. An example of the use of charin is included as Rexx_b.cmd. This program does a hex dump of itself. Not very useful, I agree, but you are welcome to customize the program for your own uses. Linein The Rexx language is a string manipulator's dream language (relative to C, PL/1, FORTRAN, Pascal, or COBOL). Because of this it is quite nice to consider an entire line at one time. This is achieved with the linein function. Linein's syntax: record = linein(myFile, start, count); Figure 6) Syntax of linein. It would follow that the parameters act just like those of charin. They don't. MyFile still contains the name of the file to be read, and defaults to the standard input if not specified. Start specifies the line you wish to place the file pointer on before the read is done. OS/2 only allows a start value of 1, the beginning of the file. Count is still the number of lines to read, but the only valid values are "1" and "0". So which function is best to perform a read? It depends. If you are performing random reads of files with constant record sizes then you might want to use charin because of its ability to position the file pointer. If there are variable length records in the file and the program considers a record at a time during processing it makes sense to use linein. There is usually a design consideration that makes one of these functions better than the other. It is a good knowledge of how each one works that gives the programmer the power to make that decision. ┌────────────────────┬────────────────────┬────────────────────┐ │ │linein │charin │ ├────────────────────┼────────────────────┼────────────────────┤ │1 byte/read │n/a │705.94 secs │ ├────────────────────┼────────────────────┼────────────────────┤ │1K bytes/read │3.7 secs │1.65 secs │ ├────────────────────┼────────────────────┼────────────────────┤ │1M bytes/read │n/a │2.6 secs │ └────────────────────┴────────────────────┴────────────────────┘ Table 1) Comparison of the performance of linein and charin by the number of characters handled when reading file with 1024 records of 1024 bytes each. Cache was cleared between each test. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.4. Writing to a File ═══ Writing to a File Each of the input functions described above, charin and linein, have twins for writing data to a file. These functions are fairly consistent with their sibling input functions, but there is a difference when these functions are used to open the file implicitly. If charout or lineout are used the file is opened for write, the file pointer is positioned at the end file, and the data to be written is appended to the file. Charout Charout will place a string into a specified file starting at any location within the file that the programmer desires. No carriage return/line feed combination is inserted after the data. count = charout(myFile, text, start); Figure 7) Syntax of charout. This function call looks much like charin with text, start, and count shifted. Text is the string to be written to the file. String can contain non-printable characters (including carriage returns and line feeds). Start, again, is the position of the file pointer before the read. The desired value of count is 0. Count does not indicate the number of bytes successfully written to the file, but indicates the number of bytes not written to the file because of some type of error. Lineout While charout could be used several times during the output of a single record, lineout will always append the text with an end of record marker. This requires the programmer to build all data for the record in a program variable. Lineout looks quite similar to its cousin, charout. count = lineout(myFile, text, start); Figure 8) Syntax of lineout. The parameters and return values are the same as charout except that they deal with lines rather than characters. The only valid value of start is "1". This will set the file pointer to the beginning of the file and existing text will be overwritten. Omit the parameter to continue writing where the file pointer currently resides. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.5. Closing the File ═══ Closing the File Either of the output functions may be used to close the file by supplying only the file name as an argument. lineout( myFile ); charout( myFile ); Figure 9) Implicitly closing a file. Either of the two functions will suffice. However, and there is always a however, if the close should fail there is no indication of this fact nor the reasons for its occurrence. The stream function should be used for programs other than personal utilities to close the file as well as open it. rc = stream(myFile, "c", "close"); Figure 10) Explicitly closing a file. The above invocation should look familiar. The diagnostics are not as descriptive for close as they are for open, but at least there is an indication of the success of the call. Should the close command fail, the stream function will return a null string. The literal "READY:" is returned after a successful close. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.6. Other File Functions of Note ═══ Other File Functions of Note Reading data from a file is fine and good, but it would be nice to know when to stop reading. I'll quickly outline two functions that exist for this purpose. Chars Chars is a function that will return the number of characters from the current location of a file pointer to the end of the file. This function can be used with the character based input function, charin, to calculate the number of times a loop needs to be iterated to read the entire file. It is suggested that chars be called once before the loop to calculate a constant value for the loop comparison rather than calling the function in the loop. Chars only accepts one argument. count = chars( myFile ); Figure 11) Syntax of chars. The above invocation will return the number of bytes from the current location of the file pointer to the end of myFile. Execution of this function against any defined OS/2 device, such as LPT1:, will always return "1". Chars cousin is lines. Lines You might think that the lines function would return the number of lines from the file pointer to the end of the file. You might have caught on by now that OS/2 has no idea how many lines there are from the current file pointer to the end of the file. Since there is no constant record structure in an OS/2 file the lines function simply returns a "1" if there are remaining lines to be read. This means that you cannot use lines to calculate a constant number of times to process a loop, but must use the function in the loop comparison. do while( lines( myFile ) ) rec = linein( myFile ) end Figure 12) Using lines in a loop. This snippet of useless code will read all of the data in myFile and stop at the end of file. The body of the loop should be customized to actually perform some useful work. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 7.7. That's the Basics ═══ That's the Basics You can't get much more basic than open, close, read, and write. There is more than one way to do each of these. The correct way depends on the context of your program and its intended audience. The important point is that your understanding of the available functions is key to your choosing the best method to fit the program's circumstances. More (and probably better) information can be obtained from OS/2's online Rexx manual. If you would like to comment on or contest any of this information please feel free to do so. My email address is in the "Contributors" section. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 8. Under the Scope ═══ ═══ 8.1. Introduction ═══ Under the Scope Written by Brad Scharf Introduction Welcome to the utility review column. This is a new column that will review freeware, shareware and commercially available applications intended to aid the development process and initially will be targeted towards beginner OS/2 programmers. The column will feature one or two utilities each month. I will try and let the reader know in advance which tools will be featured. Also, there will be an index at the end of every column that will include program names and descriptions, which issue of EDM/2 featured the program review and in future issues I will try and let the reader know where the utilities can be found and at what cost. By the way, if you have any comments or suggestions regarding this column please let me know. If the column is to be a success it will be through the feedback of its readers. Likewise, if you know of a utility that would be beneficial to other programmers please mention it and I'll do what I can to ensure that readers are made aware of it. I may be reached via the internet at schab@sasknet.sk.ca . Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 8.2. What's Reviewed ═══ What's Reviewed In my own experience, and I imagine most of your own, I have found that despite my best intentions my programs don't always behave as expected. (That must be a first!) Usually this isn't a problem but occasionally I'll compile and run a program which I then can't shutdown, even from the Window List. In addition to the above, sometimes we will write applications that modify system INI files. It's a sad fact of life that the modifications will not always be as expected, or perhaps we just wish to remove them in order to leave things as they were before testing our projects. To help us deal with both of these issues, I review in this issue a process monitor utility entitled PSPM/2, as well as an INI file editor called EDITINI. So read on! Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 8.3. PSTAT PM/2 v5.10 ═══ PSTAT PM/2 v5.10 PSTAT PM/2 (PSPM/2) is a 32-bit PM utility that provides the user with a graphical representation of running processes as well as information about those processes, such as hierarchical relationships, number of threads and thread info. All of the information that can be obtained from this program is available from the PSTAT program that ships with OS/2. In fact, PSTAT will actually provide more information than PSPM/2. The usefulness of PSPM/2 lies in its ease of use, simple visual representation of running processes, point-and-shoot capabilities, continual refresh (if desired) and perhaps most of all, the ability to terminate running processes. Unlike some other process killers, PSPM/2 works independently from OS/2s PSTAT program. The need for this type of utility first became apparent to me when, after writing my first PM program, I could not stop it from running. The appearance program icon indicated that it was running but nothing appeared on the screen, nor did the program appear in the window list. The only method available to shut down the application was to reboot my PC. Obviously this is not the preferred method of shutting down applications!. As it turned out, I had declared the window to include a menu item that I failed to provide in a resource file. Everything compiled OK but the system didn't like it very much. In comes PSPM/2... In cases as I've mentioned PSPM/2 performs very well. It allows one to obtain basic information about a running process and to shut the process down if desired. Of the many times I've used it to do this I have never found any problems. Shutting down an application is simply a matter of clicking on the process name in the main window and selecting "Terminate Process" from the resulting dialog. At this point you have one chance to change your mind when the verification dialog appears. Selecting "Yes" will terminate the process. Where PSPM/2 does not perform well is during cases of system lockup. Since the program only responds to user requests, it relies on keyboard and/or mouse input. This renders the program useless when user I/O is not possible. As a result, if your new programs locks up the system you need to reboot or make use of a different utility that allows you to recover from these situations if repeated pressing of Ctrl-Esc doesn't work. Another situation where PSPM/2 can cause problems occurs when it is used (at least on my system) to shut down PMSHELL in an attempt to reboot the Workplace Shell. This caused a blank desktop to appear with a loss of keyboard and mouse response and required a reboot of my system. Its effect on other WPS applications is unknown and would require further testing to determine its suitability for closing misbehaved WPS programs that you may be writing. Since OS/2 can behave quite differently with individual installations other users may get different results and if so I would be interested in hearing about them. Configuration of PSPM/2 is very simple. The user has one pull- down menu from which settings such as default font, window position and size, colours and refresh rate may be selected. The settings may be changed for a single session only by declining to save the selected options. There is no online help but everything is pretty straight-forward so the lack of built-in documentation should not pose problems. Overall, PSPM/2 is a nice little utility. The graphical, tree-like display provides an easy and quick way to view which processes are running. Viewing information about or termination of a process is simply a matter of clicking on the process name. As a programming aid, it has saved me much time by allowing me to close test applications by eliminating the need to reboot. While not the only utility of this type, it is a simple and effective tool well worth the storage space it takes up on your disk. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 8.4. EditINI ═══ EditINI EditINI is a simple tool that may be useful to those who create programs that modify either the OS2.INI or OS2SYS.INI files. Being even less complex than PSPM/2 this review will be short. EditINI allows the user to view, add, modify or delete information from the OS2 and OS2SYS INI files. The PM interface makes it easy to use. You select which of the INI files you wish use from one of two radio buttons, pick the application (from a drop down list-box) whose entries you wish to act upon, choose the "key name" (also from a list box) and view or modify the data under that key name. This isn't a bad little utility if your applications make few modifications to the INI files, but for programs that make lots of additions to these files, EditINI, while still useful, can be time-consuming. There can (and probably will) be dozens of application entries and each application in turn can have many more entries in the "key names" and data fields. This isn't a problem when manually changing settings in the INI files, but can be time consuming when deleting all references to a program because the list boxes are of the style "single selection". To make matters worse, after deleting an entry, the lists are reset to the top. Applications can only be deleted by first removing all "key names" (one at a time) and if an application has made many entries into the INI files it may take a while to remove all references to it because you have to find (again) the application name and then the key name from lists that can be fairly long. If your program does make lots of entries, it may be best to create a separate INI file for use during the testing phase of development and then, when everything has been debugged, simply change the code to use the system INI files instead of an application-specific one. This won't work in all cases, as you may need to register new objects or data types etc., but placing as many profile items as possible into a separate file during development can save a lot of time. This way, if things don't go as they should, you can simply delete the new INI file and try again. As you can probably tell from this text, I'm a firm believer in the hit-and-miss approach!. Where this program can be really convenient is when writing your first applications that read and write to the INI files. Since we all know it's safer to read from than to write to a file, you can use EditINI to make INI file entries manually, perfect the code that reads the information first and then worry about the code that writes information. For beginners this is ideal because it allows one to get some experience with the profile functions without the worry of destroying important system files. For the more advanced user, any information contained in the OS2 and OS2SYS INI files can be viewed, modified or deleted. Since there are too many to list, I'll assume you know what INI entries you need to access but rest assured that if it exists in these files, you can get at it with EditINI. Despite having mentioned more dislikes than likes about this program, I do like it and would have had more good things to say if it weren't so simplistic. As a tool, especially for beginners, it is very useful and should be part of your collection. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 8.5. Index ═══ Index This index is intended to give you an overview of the products reviewed and will eventually contain other pertinent information such as an overall rating and a brief summary of the product reviewed. Each table is assigned a category and contains products which fall into that category; however, as more products are reviewed, the category list will be expanded and some categories might be renamed to more accurately reflect their contents. System Information Utilities ┌────────────────────┬──────────┐ │Program │Issue │ ├────────────────────┼──────────┤ │PSPM/2 │4-1 │ └────────────────────┴──────────┘ INI File Editors ┌────────────────────┬──────────┐ │Program │Issue │ ├────────────────────┼──────────┤ │EditINI │4-1 │ └────────────────────┴──────────┘ Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9. Contributors to this Issue ═══ Are You a Potential Author? We are always looking for authors. If you have a topic about which you would like to write, send a brief description of the topic electronically to any of the editors by the 15th of the month before the month in which your article will appear. This alerts us that you will be sending an article so that we can plan the issue layout accordingly. After you have done this, read the latest copy of the Article Submission Guidelines on our web site or download them to your machine also from our web site. These guidelines contain everything you need to know about writing an article for EDM/2. The editors can be reached at the following email addresses:  Larry Salomon - larry_salomon@iqpac.com (Internet).  Carsten Whimster - carsten_whimster@iqpac.com (Internet). The following people contributed to this issue in one form or another (in alphabetical order):  Edward Boykin  Larry Salomon, Jr.  Brad Scharf  Carsten Whimster  Joe Wyatt  Gordon Zeglinski  Network distributors Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.1. Edward Boykin ═══ Edward Boykin Ed Boykin will graduate this winter from Georgia Institute of Technology with a Bachelors' Degree in Aerospace Engineering. He has been studying programming on his own for about three years and will probably be continuing at Tech to get a Master's degree in Computer Science or Engineering. His current OS/2 projects include a POP and SMTP e-mail program for OS/2 and other network client/server projects. He is currently working as an intern for Racetrac Petroleum Corp. doing client/server programming using Microsoft Windows NT and Oracle. He can be reached at aviator@mindspring.com or on the IRC #OS/2 channel as Av8| Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.2. Larry Salomon, Jr. ═══ Larry Salomon Jr. Larry Salomon Jr. has been developing OS/2 applications since version 1.1 in 1989. He has written numerous applications, including the Scramble applet that was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen Capture trio that has been distributed on numerous CD-ROMs. Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C Programming (Wiley-QED). Finally, he is the CEO/President of IQPac Inc. which is responsible for the publication of EDM/2, and he is a frequent contributor to the publication. Larry can be reached electronically via the Internet at larry_salomon@iqpac.com. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.3. Brad Scharf ═══ Brad Scharf Brad discovered computers while enrolled in a chemistry B.S. program and soon after switched to computer science. He has been using OS/2 since the release of version 2.0, has used OS/2 exclusively since version 2.1, and is now in the process of teaching himself PM programming. Brad can be reached via the internet at schab@sasknet.sk.ca Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.4. Carsten Whimster ═══ Carsten Whimster Carsten is an undergraduate Computer Science student at the University of Waterloo. He is currently in fourth year, and enjoying it immensely. He uses Visual Age C++, Watcom C/C++ 10.0a and Watcom VX-REXX 2.0c. Carsten is the author of some commandline utilities, and POV-Panel/2. He is also a TEAM-OS/2 member, and has adopted a little computer store called The Data Store in Waterloo, Ontario. You may reach Carsten... ...via email (Internet): carsten_whimster@iqpac.com ...via the World Wide Web: http://www.undergrad.math.uwaterloo.ca/~bcrwhims/ ...via snail mail: (I am just about to move. Hang in there for a month) ...via voice: (519)886-2439 Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.5. Joe Wyatt ═══ Joe Wyatt Joe has been working in OS/2 since 1.3 and has programmed in Rexx on four different platforms. Rexx projects have included elegant, complex systems in both VM and OS/2, operating system automation in MVS, and your basic "quick and dirty" tools in DOS. He has recently mustered up the courage to jump into the world of consulting and self-employment. (God help him.) He makes his home in San Antonio, Texas with a wife and four children (along with 2 dogs, 1 cat, 1 turtle, varying numbers of fish, and a rabbit). He can be reached via internet address jwyatt@txdirect.net for comments and criticisms. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.6. Gordon Zeglinski ═══ Gordon Zeglinski Gordon Zeglinski is a freelance programmer/consultant who received his Master's degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. He has been programming in C++ for 6 years and also has a strong background in FORTRAN. He started developing OS/2 applications with version 2.0 . His current projects include a client/server communications program that utilitizes OS/2's features which has entered beta testing. Additionally, he is involved in the development of a "real-time" automated vehicle based on OS/2 and using C++ in which he does device driver development and designs the applications that comprise the control logic and user interface. He can be reached via the Internet at gordon_zeglinski@iqpac.com. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 ═══ 9.7. Network distributors ═══ Network Distributors These people are part of our distribution system to provide EDM/2 on networks other than the Internet. Their help to provide access to this magazine for others is voluntary and we appreciate them a lot!  Paul Hethmon (phethmon@utk.edu) - Compuserve  Gess Shankar (gess@knex.mind.org) - Internet  Jason B. Tiller (PeerGynt@aol.com) - America On-line  Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's If you would like to become a "network distributor", be sure to contact the editors so that we can give you the credit you deserve! Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1