home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 32 Periodic / 32-Periodic.zip / edmi4-1.zip / EDMI4-1.INF (.txt) < prev    next >
OS/2 Help File  |  1996-01-16  |  234KB  |  2,096 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Jan 1996 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                   The Electronic Developer's Magazine for OS/2
  5.                       Portions copyright (c) by IQPac Inc.
  6.                                 Volume 4, issue 1
  7.  
  8. Administrivia 
  9.  
  10. Well, here I am again, and I'm going to do what I did last month - concatenate 
  11. the "From the Editor" sections together, liberally sprinkle the <BACKSPACE> 
  12. key, and serve them up again as though fresh from the oven. However, you should 
  13. read this month's title page, if you didn't last month, because you might miss 
  14. some interesting things here that aren't anywhere else... 
  15.  
  16. Gearing Up for Games Update 
  17.  
  18. I received mail from Michael Duffy regarding the Gearing Up for Games series. 
  19. Because he now works for Stardock Systems, he is working quite a lot up to 18 
  20. hours a day, trying to meet Christmas deadlines and such.  However, he said he 
  21. does have the code done for the next part of the series and simply needs to 
  22. finish the text.  Look for this to appear in February or soon after. 
  23.  
  24. Missing in Action 
  25.  
  26. I still haven't located Johan Wikman, however.  He was writing the RMX-OS2 
  27. series, which I personally found quite interesting.  Mail to him bounces and I 
  28. have no other way of contacting him.  If you do, please do and let me know how 
  29. to contact him also. 
  30.  
  31. Best Wishes for a Speedy Recovery 
  32.  
  33. I hope that our student readers did well on their finals, especially Carsten. 
  34. He has suffered from a lack of time lately, which is why all of the typos 
  35. slipped through the cracks on the December articles.  I apologize for this, but 
  36. English was never my best subject. 
  37.  
  38. Credit Where Credit is Due 
  39.  
  40. Before I begin this week's spew of talk, I would like to publicly thank Rocco 
  41. Caputo for the immense and intense amount of help he provided to me last month 
  42. on the Perl script that processes the new Search facility on the web site. 
  43.  
  44. comp.os.os2.announce , Etc. 
  45.  
  46. Eh?  New Search facility? 
  47.  
  48. If you haven't been keeping in touch with the net over the holidays, EDM/2 has 
  49. announced (by the time you read this) a permanent home for the web version of 
  50. the publication.  (Actually, the home belongs to IQPac Inc. but who's 
  51. counting?)  The new URL of the magazine is http://www.iqpac.com.  There are a 
  52. lot of things that are different there from what you were used to at the venus 
  53. site.  You might check out the press release that was posted to the various 
  54. newsgroups. 
  55.  
  56. If you've noticed, I've been trying harder to keep the community abreast of 
  57. things via the newsgroups comp.os.os2.announce and comp.os.os2.programmer.*. 
  58. My aim is to achieve the level of feedback that Trevor Smith (from OS/2 
  59. e-Zine!) provides in comp.os.os2.misc, but it will be difficult.  In order to 
  60. continue taking EDM/2 (and, to an extent, IQPac, Inc.) to higher levels, it is 
  61. necessary to generate and maintain a high interest level for the magazine. 
  62.  
  63. The point of this is that, although this is the preferred place for you to 
  64. watch, you can also keep an eye out in the OS/2 newsgroups for the same and 
  65. possibly additional information about EDM/2. 
  66.  
  67. More Thanks to be Spread 
  68.  
  69. This is where I would like to thank Rajv (as he is known in the #os/2 channel 
  70. on IRC) for allowing EDM/2 to spend so much time at venus on his hardware. 
  71. Without him, the web site would have "crashed and burned."  Fortunately, there 
  72. are always people out there who want to help out when help is sorely needed. 
  73.  
  74. Another Call for Writers 
  75.  
  76. Unfailingly, I get a letter or two every month from people asking if topic 
  77. such-and-such would be interesting.  Let me put this in a way everyone could 
  78. understand: 
  79.  
  80. Yes! 
  81.  
  82. (Eesh!) 
  83.  
  84. Seriously, if you have a topic that is relevant to OS/2 development, we want 
  85. you to write about it!  Read the Article Submission Guidelines first and then 
  86. start your keyboards! 
  87.  
  88. Holiday Wishes 
  89.  
  90. Although I am aware of the many religions that span our reader base, I would 
  91. like to wish everyone a happy holiday. 
  92.  
  93. Ah, how I love the holidays.  There isn't anything like lots of good music, 
  94. food, and fellowship to brighten the days during the end of December. 
  95.  
  96. You can keep the messes and the dirty dishes. 
  97.  
  98. Anyway, my family decided to brave the winter cold in New York by coming up 
  99. (from South Carolina!) to spend this week with my wife and I.  It's been fun, 
  100. and has kept us busy. 
  101.  
  102. Sockets 
  103.  
  104. Speaking of busy, I've managed to talk to a couple of people despite the 
  105. arrival of my family.  It seems that we all got the same idea and decided to 
  106. write a socket library  to help us develop our TCP/IP applications. Of course, 
  107. I did not think to ask whether they were planning to release the library to the 
  108. general public.  I would certainly hope so, however. 
  109.  
  110. Myself, if my library ever matured to the point where it was generic enough to 
  111. be usable from a variety of applications, I would release it.  Of course, the 
  112. ultimate goal for me is to fold the socket library into the Common/2 
  113. communications subsystem.  The current implementation uses named pipes, but it 
  114. would be nice to allow the application to use the same interface for both named 
  115. pipes and sockets. 
  116.  
  117. Managers and Such 
  118.  
  119. Of course, such an approach is not without its design difficulties. Although 
  120. named pipes are supported natively by OS/2, sockets are not, and the DLL's 
  121. needed by TCP/IP may or may not be there.  This immediately suggests either a 
  122. bunch of DosLoadModule() and DosQueryProcAddr() calls by Common/2 (referred to 
  123. as dynamic binding)  or a set of statically bound DLL's which are called by 
  124. Common/2. However, now I have to add error checking to insure that the 
  125. application doesn't specify a protocol that isn't installed, etc. 
  126.  
  127. As I said, this approach isn't without its difficulties. 
  128.  
  129. No More PC Week, Infoworld, etc. 
  130.  
  131. It's funny how I tout the web as the greatest thing since sliced bread, yet I 
  132. find that I am at a loss, now that I no longer will be able to browse the 
  133. printed versions of the weekly trade publications that I used to read.  I guess 
  134. I will now have to make an extra effort to set aside time at home to keep 
  135. up-to-date on the goings-on in the world. 
  136.  
  137. Does this mean the web will never entirely replace the printed publication? 
  138. Well, I don't think any of us were naive enough to believe this in the first 
  139. place.  (Remember the "paperless office"?)  However, I do think that industry 
  140. analysts overestimate the worth of the web, from the user's point of view.  I 
  141. guess that, until ISDN and other forms of high speed, digital communication 
  142. capabilities become available and more popular, the status quo will rule. 
  143. Watch, though, for the day when it changes, because I believe it will change 
  144. quickly. 
  145.  
  146. New Books 
  147.  
  148. 'Ever wanted to write a book?  Although OS/2 seems to be catching up to Windows 
  149. in terms of the number of books it has available, it still has quite a long way 
  150. to go.  If you think you have the ability and the time and the desire to stay 
  151. committed to completing a tome, then you should see what you can do to get a 
  152. publisher to sponsor you.  This thought arose because it seems that I've 
  153. started receiving more and more notes that begin with:  "since you have made 
  154. the rounds in book publishing..." 
  155.  
  156.  
  157. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  158.  
  159. Copyright Notice 
  160.  
  161. EDM/2 is published by IQPac Inc.  IQPac Inc. can be reached via U.S. Mail at 
  162. the following address: 
  163.  
  164. IQPac Inc.
  165. 7 East Broadway, Box 804
  166. New York, NY 10038
  167. U.S.A.
  168.  
  169.  Editor-in-chief     Larry Salomon Jr. (larry_salomon@iqpac.com) 
  170.  Associate editor    Carsten Whimster (carsten_whimster@iqpac.com) 
  171.  Contributing editor Gordon Zeglinski (gordon_zeglinski@iqpac.com) 
  172.  
  173.  CEO/President       Larry Salomon Jr. (larry_salomon@iqpac.com) 
  174.  
  175.  All material is copyrighted by its original author.  No part of this magazine 
  176.  may be reproduced without permission from the original author. 
  177.  
  178.  This publication may be freely distributed in electronic form provided that 
  179.  all parts are present in their original unmodified form.  A reasonable fee may 
  180.  be charged for the physical act of distribution; no fee may be charged for the 
  181.  publication itself. 
  182.  
  183.  Neither IQPac Inc. nor this publication are affiliated with International 
  184.  Business Machines Corporation. 
  185.  
  186.  OS/2 is a registered trademark of International Business Machines Corporation. 
  187.  Other trademarks are property of their respective owners.  Any mention of a 
  188.  product in this publication does not constitute an endorsement or affiliation 
  189.  unless specifically stated in the text. 
  190.  
  191.  The OS/2 Accredited Logo is a trademark of International Business Machines 
  192.  Corporation and is used by IQPac Inc. under license.  This On-line Publication 
  193.  is independently produced by IQPac Inc. and IBM is not responsible in any way 
  194.  for its contents. 
  195.  
  196.  IQPac Inc. is an accredited member of the IBM Independent Vendor League. 
  197.  
  198.  Copyright Notice - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  199.  
  200.  
  201. ΓòÉΓòÉΓòÉ 3. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  202.  
  203. How Do I Get EDM/2? 
  204.  
  205. EDM/2 can be obtained in any of the following ways: 
  206.  
  207. Anonymous FTP on the Internet 
  208.  
  209. hobbes.nmsu.edu in the /os2/newsltr directory. 
  210.  
  211. ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  212.  
  213. Elsewhere on the Internet 
  214.  
  215. generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  216.  
  217. The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org to 
  218. receive a file containing (among other things) instructions for subscribing to 
  219. EDM/2. 
  220.  
  221. On Compuserve 
  222.  
  223. All back issues are available in the forum OS2DF2, section 15. 
  224.  
  225. On BBS's 
  226.  
  227. From BBS's in Denmark, send email to Jesper Nielsen at 
  228. afdata@pop02.ny.us.ibm.net for a location near you. 
  229.  
  230. How do I Get EDM/2? - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  231.  
  232.  
  233. ΓòÉΓòÉΓòÉ 4. Plugging Into OS/2 Socket Programming (Part 3) ΓòÉΓòÉΓòÉ
  234.  
  235.  
  236. ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
  237.  
  238.  Plugging Into OS/2 Socket Programming (Part 3) 
  239.  
  240. Written by Edward Boykin 
  241.  
  242. Introduction 
  243.  
  244. Welcome to my third article on OS/2 socket programming.  We are finally going 
  245. to look at a more advanced client-server setup.  This month, I will discuss 
  246. only the client part and treat the server only as a 'black box' so that you may 
  247. concentrate on one half of the set up.  I have included only the client source 
  248. and executables, but in order to make the client usable I wrote it so it would 
  249. work with an internet "chat" type server (not IRC) that already exists.  The 
  250. server to be connected with is hard-coded in the client source. Next month I 
  251. will update the client so you can connect to the server I am writing. 
  252.  
  253. For some of you who have been unable to work with sockets because of the cost 
  254. of the IBM TCP/IP toolkit, I have some good news:  it has come to my attention 
  255. that the Warp Connect CD-ROM contains all the headers, libraries and DLLs of 
  256. the toolkit; however, it does not contain documentation.  If you own this CD 
  257. then do a search for the "toolkit" directory and you will find this zip file 
  258. there.  (Those of you who do not have Warp Connect are still out of luck, 
  259. unfortunately.) 
  260.  
  261. On to the show... 
  262.  
  263. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, 
  264. Issue 1 
  265.  
  266.  
  267. ΓòÉΓòÉΓòÉ 4.2. The Select() Function ΓòÉΓòÉΓòÉ
  268.  
  269. The Select() Function 
  270.  
  271. In my study of socket programming, I found that only one function really ever 
  272. confused me and that was the select() function.  There are two versions of 
  273. select() in the OS/2 socket SDK:  one version is the same as the BSD socket 
  274. call which uses bitmasks and such to set up the function; the other is IBM's 
  275. version of the function with the same name.  I found the former to be too 
  276. difficult to use so I opted to use the latter instead. 
  277.  
  278. The select() function is used to check one or many socket descriptors for 
  279. readability, writability, and exceptions.  The function looks like this: 
  280.  
  281. int select ( int *socks,
  282.              int noreads,
  283.              int nowrites,
  284.              int noexcept,
  285.              int timeout );
  286.  
  287. Figure 1)  IBM's version of the select() function. 
  288.  
  289. The first parameter is an array which contains the socket descriptors you wish 
  290. to perform the select call on.  When creating this array, place all of the 
  291. sockets you wish to check for readability first, then for writability, and 
  292. finally for exceptions.  So, you could theoretically have an array of three 
  293. integers with the same integer, or socket descriptor, in all three places, 
  294. meaning that you want to see if you can read from and write to the socket and 
  295. check for any socket exceptions.  The next three parameters tell select how 
  296. many sockets in that array are for reading, writing and exception checking. The 
  297. final parameter is a timeout value.  This value is in seconds and determines 
  298. how long the select call will block if none of the sockets check out.  If you 
  299. make this value 0 select will not block, and if you make it -1 select will not 
  300. timeout. 
  301.  
  302. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, 
  303. Issue 1 
  304.  
  305.  
  306. ΓòÉΓòÉΓòÉ 4.3. The Anatomy of a Client ΓòÉΓòÉΓòÉ
  307.  
  308. The Anatomy of a Client 
  309.  
  310. The client I have provided for this article is a very simple, PM based TCP 
  311. packet client.  In a nutshell, it connects to a server and sends and receives 
  312. packet to and from the server.  The server allows multiple client connections 
  313. and when one client sends a message the server relays that message to all of 
  314. the other connected clients.  This is what allows the network "chatting" to 
  315. take place. 
  316.  
  317. A good client application should have at least the following capabilities. Of 
  318. course, it needs to be able to send and receive messages quickly with these 
  319. message being of some standardized protocol.  It should also be able to connect 
  320. to any server which supports the particular chat protocol.  (This ability will 
  321. be available in the next article.)  The client should have an easy to use user 
  322. interface.  And, finally, the client should be easily enhanced. 
  323.  
  324. The User Interface 
  325.  
  326. I mentioned before that the client was to be PM based.  I did this to make it 
  327. easier to handle user input and server output.  The interface for the sample 
  328. client is a simple one.  It contains two buttons, a read-only multiple line 
  329. editor, and an entry field.  One button is for connecting to the server and the 
  330. other for disconnecting while the MLE is for server output and the entry field 
  331. is for user input.  It is a crude, but effective, interface for our needs. 
  332.  
  333. A more advanced client interface might allow for drag-n-drop font changes or 
  334. dynamic font changing based on the dimensions of the main window, etc. These 
  335. things, however, are for the future. 
  336.  
  337. The Packet Protocol 
  338.  
  339. The packet protocol I have selected is one which is used by the "Internet 
  340. Citizens Band", or ICB, servers for years.  A single packet to or from the 
  341. client contains three parts and has the form:  "l p m", where l is a single 
  342. byte which specifies the total length of the packet including itself, p is the 
  343. packet type indicator, and m is the packet data.  The current client only 
  344. supports the login packet, a, and the open message packet, b, for the packet 
  345. type. 
  346.  
  347. Even though we have a limited number of packet types right now, by including 
  348. this byte of information we are not limited to just these packet types - the 
  349. "Internet Citizens Band" server actually supports many other packet types.  I 
  350. have limited this client only for simplicity's sake.  The single byte of the 
  351. length does pose one restriction, however, and that is that the total length of 
  352. message can only be 253 bytes since the length byte includes the protocol type 
  353. and itself in that length. 
  354.  
  355. Sending Packets 
  356.  
  357. Sending packets is very simple.  I have defined a user message called SM_SEND 
  358. which, when sent to the send/receive thread, tells the thread that there is an 
  359. outgoing message.  The message contains a pointer to the already prepared 
  360. packet in mp1. 
  361.  
  362. Receiving Packets 
  363.  
  364. Receiving packets is accomplished in almost the same way as sending them. When 
  365. the send/receive thread loop receives a packet, it is broken down by removing 
  366. the l (size) and p (packet type) from the string and then runs through a case 
  367. statement to determine the packet type. Since the client only supports the b 
  368. (open message) packet type, this is the only case we look for.  We also define 
  369. a default which takes any of the other packets from the server and ignores 
  370. them.  Once it is determined that a complete open message packet has been 
  371. received the thread then sends another user message, SM_RECV, to the user 
  372. interface thread.  Once again mp1 contains a pointer to the message string. 
  373.  
  374. Enhancing the Client 
  375.  
  376. It should be obvious how the client is easily enhanced in the last few 
  377. sections.  I have used a packet protocol which allows for a byte to specify a 
  378. different kind of packet.  This could include private messages, specially 
  379. formatted open messages, or just about anything else you can think of.  We 
  380. could create a broken up message which could be any packet type that was over 
  381. 253 bytes.  The packet could then be broken into 253 byte chunks and sent 
  382. separately.  The possibilities are almost endless here.  Imagination is the 
  383. only limit. 
  384.  
  385. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, 
  386. Issue 1 
  387.  
  388.  
  389. ΓòÉΓòÉΓòÉ 4.4. The Operation of CLIENT.EXE ΓòÉΓòÉΓòÉ
  390.  
  391. The Operation of CLIENT.EXE 
  392.  
  393. Now that I have described what goes into the client program I will begin to put 
  394. it all together.  As I said before, the client contains two threads.  I will 
  395. call this the user interface thread and the send/receive thread.  The user 
  396. interface thread handles the user input and server output and the connection of 
  397. the client to the server.  The send/receive thread handles the sending and 
  398. receiving of message packets to and from the server.  The two threads will talk 
  399. to each other via user defined messages. 
  400.  
  401. Take a look at Figure 2. I have diagrammed the basic execution layout of the 
  402. client program there.  I will start with the top of the diagram in the user 
  403. interface thread and work may way over. 
  404.  
  405. Figure 2)  Execution path of client. 
  406.  
  407. Initializing the Client Application 
  408.  
  409. Upon initial client startup the main window is displayed.  You must supply a 
  410. nickname on the command line when you start CLIENT.EXE.  At this point the user 
  411. should press the "Connect" button.  The connect button send a WM_COMMAND 
  412. message with the button id, ID_CONNECT, as one of its parameters which the 
  413. window procedure handles by calling a function setupSockets().  SetupSockets() 
  414. will initialize the socket environment and create the socket that the client 
  415. will use to communicate with the server.  If this all occurs normally then 
  416. setupSockets() will return the socket descriptor that was created. If all does 
  417. not go well then it will return 0 or a negative number.  If it is a negative 
  418. number then this is the error code multiplied by -1. 
  419.  
  420. Assuming we had a good socket returned then WinPostMsg() is used to send a 
  421. SM_SOCKETGO message.  The basic structure is in the code to add some kind of 
  422. error notification to the user but for times sake I did not include anything to 
  423. that effect. 
  424.  
  425. Connecting to the Server 
  426.  
  427. The SM_SOCKETGO message is used to tell the client that the socket environment 
  428. is all set up ready to go and we need to connect to the server now.  The 
  429. message will be handles by calling the connectToServer() function.  We send to 
  430. this function our socket descriptor, the server name, and the server port.  I 
  431. have defined, in client.h, the server to be icb.sjsu.edu and the port to be 
  432. 7326. Leave these be until next month when I will have the server ready for 
  433. you. 
  434.  
  435. ConnectToServer() does just that - it connects to the server. It sets up the 
  436. necessary hostent struct which is used by the socket function connect() to 
  437. determine the place we want to connect to.  Notice we are using the 
  438. gethostbyname() function in order to determine icb.sjsu.edu's interment IP 
  439. address.  Upon a successful connection the function loginToServer() is called. 
  440. The parameters to this function are the socket descriptor and your chosen 
  441. nickname. 
  442.  
  443. LoginToServer() gives us our first look at sending and receiving a message 
  444. packet.  This is the only time that message will be sent or received outside of 
  445. the send/receive thread.  The comments at the beginning of the function 
  446. describe the format of the login packet.  Notice that fields are separated by a 
  447. ^A or \001 character.  This is part of the standard message packet protocol so 
  448. if you were to create some new message packet type that used fields you would 
  449. want to use that character to separate them.  If you follow through the first 
  450. couple lines of actual code you will see how I go about assembling the message 
  451. packet for our login. 
  452.  
  453. The first communication activity that takes place is the reception of the 
  454. protocol packet from the server.  This is the server saying "hi there".  Using 
  455. a bit of string and pointer acrobatics, I take the two fields of this packet 
  456. and create the connect message to be displayed on the MLE.  The last thing to 
  457. do is to send that login packet that was put together.  If all goes well the 
  458. function will return TRUE; else it will return FALSE to the caller, the 
  459. connectToServer() function.  A TRUE return code will cause a SM_CONNECTED 
  460. message to be posted; otherwise the message "Unable to Connect to Server" is 
  461. displayed on the MLE. 
  462.  
  463. The SM_CONNECTED message tells the client that all is ready for normal 
  464. communications with the server.  The message is handled by calling 
  465. _beginthread() to start up the send/receive thread. 
  466.  
  467. The Send/Receive Thread Loop 
  468.  
  469. We now come to the meat of the client application.  It is here that all further 
  470. communication between the client and the server will take place.  The thread 
  471. basically executes an continual loop until either we shut down or the server 
  472. shuts us down.  This loop has two sections: 
  473.  
  474.      Check message loop for outgoing messages. 
  475.  
  476.       If there are some, then call select() to check for writeability of socket 
  477.       Continue until all messages are sent or select() returns a not ready. 
  478.  
  479.      Check socket for readability by letting select() run for a few seconds 
  480.       before returning. 
  481.  
  482.       Process any incoming messages and pass them on by using SM_RECV messages. 
  483.  
  484.  The fist part of the loop checks for incoming SM_SEND, or SM_KILL messages. 
  485.  This is pretty self explanatory.  If an SM_SEND message is received then the 
  486.  first message parameter, mp1, is used as the pointer to the message to be 
  487.  sent. Select() will be called to check the socket for writeability.  If the 
  488.  socket is ready to have data sent out then all that is needed is to call the 
  489.  send() function.  The packet is contained in a chunk of allocated memory 
  490.  pointed to by the SM_SEND message's mp1 parameter.  Some error checking should 
  491.  be used here to insure that all the bytes were sent.  The last step is to free 
  492.  the allocated memory which contains the packet.  This process will continue 
  493.  until no more messages are in the queue. 
  494.  
  495.  The SM_KILL message can also be received.  The user defined message is used to 
  496.  tell the send/receive thread to shutdown the socket connection and end the 
  497.  thread.  To do this soclose() is called and the Connected variable is set to 
  498.  FALSE. 
  499.  
  500.  If there are no messages to read or once all of the messages have been read 
  501.  and processed and no SM_KILL messages were received then the socket will be 
  502.  checked for incoming packets from the server.  To do this, select() is called 
  503.  again.  I included a timeout value of 5 seconds just to give the receive 
  504.  section a chance to get some data in if there is none at the moment. 
  505.  
  506.  If select() returns a ready socket then the first byte is read to determine 
  507.  the length of the incoming packet.  Another read is then done to read in just 
  508.  that amount of data specified in the first byte.  After checking to be sure we 
  509.  got the correct amount of data in, the packet type is checked in a switch() 
  510.  statement.  If the packet type is b, open message, then the packet message is 
  511.  sent to the user interface thread via the SM_RECV thread.  If a packet type is 
  512.  received which is not supported then the memory that contains it is freed. 
  513.  
  514.  This loop continues indefinitely until the SM_KILL is received or the program 
  515.  is terminated. 
  516.  
  517.  The User Interface Thread 
  518.  
  519.  The user interface thread, as I said before, is responsible for handling the 
  520.  user input and server output.  The whole thread runs off of a standard client 
  521.  window procedure. 
  522.  
  523.  The user input part is fairly simple.  The message loop captured the WM_CHAR 
  524.  message and looks for the enter or return key to have been pressed.  It then 
  525.  queries the text in the WND_INPUT window and if there is text in there it 
  526.  processes the string. 
  527.  
  528.  To process the string, the string, open message packet type, and packet length 
  529.  byte is inserted into a 256 byte character string.  A null terminator is added 
  530.  to specify the end of the created string.  The message packet is then sent to 
  531.  the send/receive thread via the SM_SEND message.  The final thing done is to 
  532.  show the user his own message on the output window. 
  533.  
  534.  The server output is handled a bit differently.  Once the SM_RECV message is 
  535.  received another series of string acrobatics is done to break the fields of 
  536.  the packet up.  When we receive an open message packet from the server it 
  537.  contains 2 fields.  The first field is the nickname of who sent the message 
  538.  and the seconds is the message itself.  Once the packet is broken up it is 
  539.  then displayed on the output window. 
  540.  
  541.  Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, 
  542.  Issue 1 
  543.  
  544.  
  545. ΓòÉΓòÉΓòÉ 4.5. Wrap Up and Next Time ΓòÉΓòÉΓòÉ
  546.  
  547. Wrap Up and Next Time 
  548.  
  549. Well, we are almost finished.  This month I have use a simple client 
  550. application which allows a chat over TCP/IP networks.  Please examine the code 
  551. and try to understand how I have integrated the socket functions into a PM 
  552. program and how things like the select() call work.  If you have any questions 
  553. I can always be reached at aviator@mindspring.com. 
  554.  
  555. Next time I will include a server which you can set up yourself and allow 
  556. anyone on your network to chat.  I will also change the client code so you can 
  557. specify what server you want to use.  Thanks for you time.  I hope you have 
  558. learned a lot. 
  559.  
  560. Plugging Into OS/2 Socket Programming (Part 3) - EDM/2 - Jan 1996 - Volume 4, 
  561. Issue 1 
  562.  
  563.  
  564. ΓòÉΓòÉΓòÉ 5. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
  565.  
  566.  
  567. ΓòÉΓòÉΓòÉ 5.1. Introduction ΓòÉΓòÉΓòÉ
  568.  
  569. /dev/EDM2/BookReview 
  570.  
  571. Written by Carsten Whimster 
  572.  
  573. Introduction 
  574.  
  575. In /dev/EDM2/BookReview, I focus on development books and materials.  I have 
  576. written this column from the point of view of an intermediate PM C programmer 
  577. and intermediate REXX programmer.  Pick up whichever book strikes your fancy, 
  578. and join the growing group of people following our PM programming columns.  I 
  579. have already reviewed a number of beginner's books, and will try to concentrate 
  580. a bit more on intermediate techniques and special topics from now on. 
  581.  
  582. Please send me your comments and thoughts so that I can make this column what 
  583. you want it to be.  I read and respond to all mail. 
  584.  
  585. OS/2 Warp Presentation Manager API is a new reference book from Wiley which 
  586. covers the Presentation Manager API (surprise), both documented and 
  587. undocumented. 
  588.  
  589. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  590.  
  591.  
  592. ΓòÉΓòÉΓòÉ 5.2. Errata ΓòÉΓòÉΓòÉ
  593.  
  594. Errata 
  595.  
  596. My Web page now has a new section on publishers, including a list of currently 
  597. available books from each publisher.  If you have any comment, mail me.  If you 
  598. have any additions or corrections, mail me.  Note the change of URL too.  Check 
  599. it out at http://www.undergrad.math.uwaterloo.ca/~bcrwhims/os2/index.html . 
  600.  
  601. I have been using my new copy of VAC++ and the WorkFrame is slow, even with C 
  602. programs.  I also don't seem to be able to turn off all the informational 
  603. messages that a compile brings up.  I have them turned off for the compiler 
  604. itself, but the rest of them are as healthy as ever, completely cluttering up 
  605. even a routine compile.  Oh well, it works well enough I guess.  I did run into 
  606. some problems when I wanted a stand-alone program.  I was using the math 
  607. library, but in spite of an include, the linker could not find the library, and 
  608. the compile would not consistently finish.  Sometimes it would, but mostly it 
  609. wouldn't.  Eventually I just created a table of cos and sin values in my header 
  610. file, but what a hazzle.  Other than the speed, the message overdose, and the 
  611. math compilation problems, it is a great environment, and I am taking to LPEX 
  612. quicker than I thought I would.  The speed, though, the speed.  On a DX4-100 
  613. with 20Mb it really ought to fly, but no such luck.  I hope they rewrite it in 
  614. VAC++ rather than Smalltalk next time.  I should be releasing a small utility 
  615. soon, and perhaps write an article for EDM/2 on the problems I had to solve 
  616. while coding. 
  617.  
  618. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  619.  
  620.  
  621. ΓòÉΓòÉΓòÉ 5.3. OS/2 Warp Presentation Manager API ΓòÉΓòÉΓòÉ
  622.  
  623. OS/2 Warp Presentation Manager API 
  624.  
  625. This month's book is second in a new series of three API references from John 
  626. Wiley and Sons, covering the Control Program, Presentation Manager, and 
  627. Workplace Shell APIs.  This particular book also promises to cover more than 
  628. just what the Warp Toolkit online references cover, while presenting the 
  629. material in a well-structured, easy-to-use manner.  Here are the chapters: 
  630.  
  631.       1.  PM Application Setup and Cleanup 
  632.       2.  Registering and Creating Windows 
  633.       3.  Messaging 
  634.       4.  Keystrokes and Focus 
  635.       5.  Presentation Spaces and Device Contexts 
  636.       6.  Window Drawing Functions 
  637.       7.  Clipping and Invalid Regions 
  638.       8.  Menus 
  639.       9.  Dialogs 
  640.       10.  Standard Dialogs 
  641.       11.  Resources 
  642.       12.  Help 
  643.       13.  Window Information 
  644.       14.  System Information 
  645.       15.  Atoms 
  646.       16.  The Clipboard and Dynamic Data Exchange 
  647.       17.  Rectangles 
  648.       18.  Task List Functions 
  649.       19.  Workplace Shell Functions 
  650.       20.  National Language Support 
  651.       Appendix A.  WinLockVisRegions 
  652.  
  653.  Similar to last month's book, publishing deadlines did not allow the 
  654.  development of a full complement of examples for each API, but there are a few 
  655.  this time.  The major difference between this book and last month's book is 
  656.  that I find the chapter introductions a little more sketchy.  Perhaps that was 
  657.  necessary to keep the book a similar size, but I prefer slightly more detailed 
  658.  descriptions, and the PM Win functions really require this unless you have 
  659.  already used them. 
  660.  
  661.  Like the previous book, the organization of the book is as follows: 
  662.  
  663.      each major topic is given its own chapter (see above) 
  664.      each chapter has a few introductory paragraphs, tutorial in nature 
  665.      each function which comes under this chapter's heading is then given, as 
  666.       follows: 
  667.         -  name and type of API (ie. chapter heading repeated) 
  668.         -  brief description 
  669.         -  syntax 
  670.         -  parameters, each with a brief explanation, and tables of possible 
  671.            values, if appropriate 
  672.         -  returns, with value and description of error codes 
  673.         -  other info, including include file, define, ordinal, and DLL API 
  674.            resides in 
  675.         -  see also, with related APIs, each with a page number 
  676.         -  notes, including warnings, restrictions and so on 
  677.  
  678.  This very simple layout makes it very simple to navigate, and powerful, 
  679.  although having used this book for the better part of a month, I find that 
  680.  this layout does compromise the quick-lookup ability for a single function, 
  681.  which most other reference books have.  I am undecided as to whether this 
  682.  layout is better in the end, or whether a more traditional pure-alphabetical 
  683.  layout is preferable.  In writing my current program I think the alphabetical 
  684.  approach has won so far, but perhaps in the long run, the new layout works 
  685.  best?  In any case, both work, and both have their strengths and weaknesses. 
  686.  One thing is for sure, I like the OTHER INFO section, with its INCLUDE 
  687.  information.  Now my utility has only the necessary includes, and whether that 
  688.  makes a difference or not to the size of the compiled program or the 
  689.  compilation speed, I feel better about it.  I have never liked the fact that 
  690.  all functions in a library get brought in by C, whether you need them or not. 
  691.  
  692.  That is it, for the second time!  I have been much busier this month, so I 
  693.  didn't get all the way through this book like last month.  With this type of 
  694.  reference that really isn't necessary though.  The functions are all there, 
  695.  and the first appendix even has a late-breaking addition of the 
  696.  WinLockVisRegions function.  I am not sure why it is here, and not in the main 
  697.  part, since it is documented in the pmwin.h file, but perhaps it wasn't in 
  698.  previous versions and only just made it in time for publicat ion. 
  699.  
  700.  This review is a little short again, but this month I won't include a sample 
  701.  function since it is so similar in layout to the original book in the series. 
  702.  I will instead just add a example of the sample code that is in a very few 
  703.  functions in this book.  This one is for WinBeginPaint(), style unaltered: 
  704.  
  705.   case WM_PAINT:
  706.           {
  707.           HPS hps; // cached-micro PS handle
  708.           RECTL rcl; // bounding rectangle
  709.           hps = WinBeginPaint ( hWnd, NULLHANDLE, &rcl );
  710.           GpiErase ( hps );
  711.           WinEndPaint ( hps );
  712.   }
  713.  
  714.   return 0;
  715.  Figure 1)  Sample code from the book for the WM_PAINT message. 
  716.  
  717.  There you are, all done for this month.  This book, due to the "not quite 
  718.  enough for me" chapter introductions, and the struggle with alphabetized 
  719.  versus sectionized layout, loses the A+ of the last book, but retains an A, 
  720.  and is still a great reference book.  Another must-have from this series. 
  721.  
  722.  /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  723.  
  724.  
  725. ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
  726.  
  727. Summary 
  728.  
  729. This is now my favorite PM reference book, as well as one of my only two PM 
  730. reference books [grin].  I had a less successful time with the sectionized 
  731. layout than with the Control Program API book, perhaps because of the more 
  732. diverse nature of the mater ial, and I needed more of an explanation at the 
  733. start of each chapter, due to the more complicated nature of the material, but 
  734. got only the same level of explanation, so it gets an A instead. Still a great 
  735. book, and so far without much competition as a PM reference book in my library. 
  736. A must-have for serious PM programmers. 
  737.  
  738. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  739.  
  740.  
  741. ΓòÉΓòÉΓòÉ 5.5. Book Reviewed ΓòÉΓòÉΓòÉ
  742.  
  743. Book Reviewed 
  744.  
  745.      OS/2 Warp Presentation Manager API, Barnum 
  746.  
  747.         -  John Wiley and Sons. ISBN 0-471-03887-3. US$29.99, CAN$40 
  748.         -  OS/2 C/C++ PM Programmers 
  749.         -  A 
  750.  
  751.       This is an excellent reference to the Presentation Manager API.  It is 
  752.       very complete, but the topical layout may throw you for a loop if you are 
  753.       used to alphabetized books.  It contains syntax, usage guides, data 
  754.       structures, and sample cross-referencing.  Highly recommended. 
  755.  
  756.  Notes 
  757.  
  758.  Please note that books aimed at different audiences should only be compared 
  759.  with great care, if at all.  I intend to concentrate on the strong points of 
  760.  the books I review, but I will point out any weaknesses in a constructive 
  761.  manner. 
  762.  
  763.  Legend 
  764.  
  765.  BOOK:  The name of the book, and the author(s) 
  766.  
  767.  PUBLISHING INFORMATION:  Publishing company, ISBN, and approximate price. 
  768.  
  769.  AUDIENCE:  This is a description of the audience I think the book targets 
  770.  best.  This is not intended as gospel, just a guideline for people not 
  771.  familiar with the book. 
  772.  
  773.  MARK:  My opinion of the success of the book's presentation, and how well it 
  774.  targets its audience.  Technical content, accuracy, organization, readability, 
  775.  and quality of index all weigh heavily here, but the single most important 
  776.  item is how well the book covers what it says it covers.  Many books try to 
  777.  cover too much, and get a lower mark as a result. 
  778.  
  779.  A+        Ground-breaking, all-around outstanding book. 
  780.  A         Excellent book. This is what I want to see happen a lot. 
  781.  A-        Excellent book with minor flaws. 
  782.  B+        Very good book with minor flaws or omissions. 
  783.  B         Good book with some flaws and omissions. 
  784.  B-        Good book, but in need of improvement. 
  785.  C+        Mediocre book with some potential, but in need of some updating. 
  786.  C         Mediocre book with some good sections, but badly in need of fixing. 
  787.  C-        Mediocre book, little good material, desperately in need of an 
  788.            overhaul. 
  789.  D         Don't buy this book unless you need it, and nothing else exists. 
  790.  F         Don't buy this book.  Period. 
  791.  
  792.  COMMENTS:  This is a very brief summary of the review proper. 
  793.  
  794.  /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  795.  
  796.  
  797. ΓòÉΓòÉΓòÉ 5.6. Content Index ΓòÉΓòÉΓòÉ
  798.  
  799. Content Index 
  800.  
  801. This Content Index is designed to let you find the book that covers the topics 
  802. you need to learn about.  It will eventually have a lot of categories, with 
  803. each book being rated along each row.  These tables will be quite large, and 
  804. will continually grow, so please give me your feedback regarding what 
  805. categories you would like to see, and which you don't.  It may take me a while 
  806. to flesh them out, so have a little patience. 
  807.  
  808. BOOK LEGEND 
  809.  
  810. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  811. ΓöéCode ΓöéIssue  ΓöéTitle                                                              Γöé
  812. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  813. ΓöéRWP  Γöé2-3    ΓöéReal World Programming for OS/2 2.1                                Γöé
  814. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  815. ΓöéLPE  Γöé2-4    ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example       Γöé
  816. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  817. ΓöéODD  Γöé2-5    ΓöéWriting OS/2 2.1 Device Drivers in C                               Γöé
  818. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  819. ΓöéGPI  Γöé2-6    ΓöéOS/2 Presentation Manager GPI                                      Γöé
  820. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  821. ΓöéTAO  Γöé2-7    ΓöéThe Art of OS/2 2.1 C Programming                                  Γöé
  822. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  823. ΓöéMOR  Γöé2-8    ΓöéMastering OS/2 REXX                                                Γöé
  824. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  825. ΓöéRSH  Γöé2-9    ΓöéREXX Reference Summary Handbook                                    Γöé
  826. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  827. ΓöéADO  Γöé2-10   ΓöéApplication Development Using OS/2 REXX                            Γöé
  828. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  829. ΓöéPMP  Γöé2-11   ΓöéOS/2 Presentation Manager Programming                              Γöé
  830. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  831. ΓöéDOA  Γöé3-1    ΓöéDesigning OS/2 Applications                                        Γöé
  832. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  833. ΓöéOSP  Γöé3-2    ΓöéOS/2 Programming                                                   Γöé
  834. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  835. ΓöéTGO  Γöé3-4    ΓöéThe GUI-OOUI War                                                   Γöé
  836. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  837. ΓöéOU   Γöé3-5    ΓöéOS/2 Warp Unleashed, Deluxe Edition                                Γöé
  838. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  839. ΓöéQR1  Γöé3-6    ΓöéWIN Functions, OS/2 Quick Reference Library Volume 1               Γöé
  840. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  841. ΓöéPWG  Γöé3-7    ΓöéProgramming the OS/2 Warp Version 3 GPI                            Γöé
  842. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  843. ΓöéDHP  Γöé3-8    ΓöéDesigning High-Powered OS/2 Warp Applications                      Γöé
  844. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  845. ΓöéOCH  Γöé3-9    ΓöéOS/2 Certification Handbook                                        Γöé
  846. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  847. ΓöéCPA  Γöé3-10   ΓöéOS/2 Warp Control Program API                                      Γöé
  848. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  849. ΓöéPMA  Γöé4-1    ΓöéOS/2 Warp Presentation Manager API                                 Γöé
  850. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  851.  
  852. NOTE:  Books which cover the same material can look similar in this table, but 
  853. be different in real life.  The style of a book, for example, can not be seen 
  854. from a quick table, so make sure that you follow up by reading the reviews of 
  855. the books you find here.  Finally, be sure that the books you are comparing are 
  856. aimed at the same audiences. 
  857.  
  858. PM C BOOKS 
  859.  
  860. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  861. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéGPI    ΓöéFonts  ΓöéPrint  Γöé
  862. Γöé     Γöé     ΓöéBasics ΓöéDriver ΓöéAVIO   ΓöéIntro  Γöé       Γöé       Γöé       Γöé
  863. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  864. ΓöéRWP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé4      Γöé4      Γöé4      Γöé3      Γöé
  865. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  866. ΓöéPME  ΓöéB-   Γöé1      Γöé0      Γöé0      Γöé2      Γöé2      Γöé2      Γöé0      Γöé
  867. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  868. ΓöéODD  ΓöéA    Γöé0      Γöé5      Γöé0      Γöé0      Γöé1      Γöé0      Γöé1      Γöé
  869. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  870. ΓöéGPI  ΓöéC+   Γöé0      Γöé0      Γöé0      Γöé0      Γöé5      Γöé2      Γöé3      Γöé
  871. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  872. ΓöéTAO  ΓöéB+   Γöé3      Γöé2      Γöé1      Γöé4      Γöé1      Γöé2      Γöé0      Γöé
  873. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  874. ΓöéPMP  ΓöéA-   Γöé1      Γöé0      Γöé1      Γöé5      Γöé3      Γöé4      Γöé2      Γöé
  875. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  876. ΓöéOSP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé3      Γöé2      Γöé1      Γöé0      Γöé
  877. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  878. ΓöéQR1  ΓöéA    Γöé0      Γöé0      Γöé0      Γöé(WIN) 5Γöé0      Γöé0      Γöé0      Γöé
  879. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  880. ΓöéPWG  ΓöéA-   Γöé0      Γöé0      Γöé0      Γöé1      Γöé5      Γöé5      Γöé5      Γöé
  881. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  882. ΓöéCPA  ΓöéA+   Γöé5      Γöé0      Γöé0      Γöé0      Γöé0      Γöé0      Γöé0      Γöé
  883. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  884. ΓöéPMA  ΓöéA    Γöé0      Γöé0      Γöé0      Γöé5      Γöé1      Γöé1      Γöé1      Γöé
  885. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  886.  
  887. REXX BOOKS: 
  888.  
  889. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  890. ΓöéBOOK ΓöéMARK ΓöéREXX     ΓöéWPS      ΓöéReferenceΓöé
  891. Γöé     Γöé     ΓöéIntro    Γöé         Γöé         Γöé
  892. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  893. ΓöéMOR  ΓöéB    Γöé4        Γöé0        Γöé2        Γöé
  894. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  895. ΓöéRSH  ΓöéA    Γöé1        Γöé2        Γöé5        Γöé
  896. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  897. ΓöéADO  ΓöéA-   Γöé3        Γöé2        Γöé4        Γöé
  898. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  899.  
  900. SYSTEM AND NON-PROGRAMMING BOOKS: 
  901.  
  902. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  903. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéThread ΓöéGPI    ΓöéFonts  ΓöéPrint  ΓöéWPS    Γöé
  904. Γöé     Γöé     ΓöéBasics ΓöéDriver ΓöéAVIO   Γöé       Γöé       Γöé       Γöé       Γöé       Γöé       Γöé
  905. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  906. ΓöéDOA  ΓöéA    Γöé4      Γöé4      Γöé2      Γöé4      Γöé5      Γöé3      Γöé2      Γöé3      Γöé0      Γöé
  907. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  908. ΓöéTGO  ΓöéB    Γöé0      Γöé0      Γöé0      Γöé2      Γöé1      Γöé0      Γöé2      Γöé1      Γöé5      Γöé
  909. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  910. ΓöéOU   ΓöéA+   Γöé1      Γöé4      Γöé4      Γöé5      Γöé2      Γöé5      Γöé5      Γöé5      Γöé5      Γöé
  911. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  912. ΓöéDHP  ΓöéA    Γöé4      Γöé4      Γöé2      Γöé4      Γöé5      Γöé3      Γöé2      Γöé3      Γöé1      Γöé
  913. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  914. ΓöéOCH  ΓöéA    Γöé?      Γöé?      Γöé?      Γöé?      Γöé?      Γöé?      Γöé?      Γöé?      Γöé?      Γöé
  915. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  916.  
  917. RATINGS LEGEND: 
  918.  
  919. ΓöîΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  920. Γöé0ΓöéNo coverage           Γöé
  921. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  922. Γöé1ΓöéVery light coverage   Γöé
  923. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  924. Γöé2ΓöéIntroductory coverage Γöé
  925. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  926. Γöé3ΓöéGood Coverage         Γöé
  927. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  928. Γöé4ΓöéIn-depth coverage     Γöé
  929. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  930. Γöé5ΓöéAuthoritative         Γöé
  931. ΓööΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  932.  
  933. /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  934.  
  935.  
  936. ΓòÉΓòÉΓòÉ 5.7. Coming Up ΓòÉΓòÉΓòÉ
  937.  
  938. Coming Up 
  939.  
  940. I will now take a break from this API series, both because I have a few other 
  941. books lined up, and also because I have not done any WPS programming, and so 
  942. need to get going on that before I can do a proper review of it.  I will likely 
  943. review Programming in REXX or The REXX Cookbook next month, or perhaps The OS/2 
  944. Warp Programmer's Sidekick, which I have found quite useful recently. 
  945.  
  946. Books I have: 
  947.  
  948.      OS/2 Warp Workplace Shell API, Pollack 
  949.      The OS/2 Warp Programmer's Sidekick, Diviney and Murray 
  950.      Programming in REXX, Daney 
  951.      The REXX Cookbook, Callaway 
  952.  
  953.  Other books I would like to review: 
  954.  
  955.  The Design of OS/2, 2nd Edition, Kogan and Deitel - I am having trouble 
  956.  getting a copy of this, so if anyone can help, please do.  A 1st edition would 
  957.  do me fine too. 
  958.  
  959.  OS/2 C++ Class Library:  Power GUI Programming with C-Set++, Law, Leong, Love 
  960.  and Tsuji - This is on the way I am told. 
  961.  
  962.  OS/2 Presentation Manager GPI, 2nd edition, Winn - I really would like to 
  963.  review this soon, as I am coming across some stuff that the old one doesn't 
  964.  handle in an up-to-date manner, and want to see what the new one is all about. 
  965.  
  966.  Visual Age:  Concepts and Features, ?  - This sounds interesting. 
  967.  
  968.  If anyone has a book they want to see reviewed, I will be happy to oblige. 
  969.  Just mail me and tell me which.  Publishers can send me books at the address 
  970.  on my personal page at the end of the magazine, and I will review all OS/2 
  971.  development-related a nd advanced user books I receive. 
  972.  
  973.  /dev/EDM2/BookReview - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  974.  
  975.  
  976. ΓòÉΓòÉΓòÉ 6. OOPS Avenue ΓòÉΓòÉΓòÉ
  977.  
  978.  
  979. ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
  980.  
  981. OOPS Avenue 
  982.  
  983. Written by Gordon Zeglinski 
  984.  
  985. Introduction 
  986.  
  987. So what happened to the rest of the screen saver DTS series?  Seems life is 
  988. full of mini-disasters up here.  Last month I injured my shoulder which made 
  989. typing impossible.  This month I had to reinstall OS/2 and reformat the hard 
  990. disk.  I have not yet reinstalled the SOM toolkit or Metaware's High C/C++. 
  991. Until I have time to do so, the DTS articles will have to wait.  Instead, we 
  992. will talk this month about C++ exceptions. 
  993.  
  994. C++ exceptions are a powerful method of handling special cases. Traditionally, 
  995. one might do something like: 
  996.  
  997. switch( foo(MyArguement,&var) ){
  998.     case 0:     //alls well
  999.         break;
  1000.     case 1:
  1001.         foo(0,&var);    //myarguement is invalid..
  1002.         break;
  1003.     case 2;             //out of memory or other serious error
  1004.         exit(2);
  1005.         break;
  1006.     default:
  1007.         fprintf(stderr,"Unknown Error returned from foo\r\n");
  1008.         break;
  1009. }
  1010.  
  1011. Figure 1)  Traditional method of error code handling. 
  1012.  
  1013. Depending on the return value from foo(), an error condition may or may not 
  1014. exist.  Exceptions follow a similar concept but are far more powerful. 
  1015.  
  1016. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1017.  
  1018.  
  1019. ΓòÉΓòÉΓòÉ 6.2. What is Exactly is a C++ Exception? ΓòÉΓòÉΓòÉ
  1020.  
  1021. What is Exactly is a C++ Exception? 
  1022.  
  1023. An exception is an object designed by the programmer specifically to relay 
  1024. error information.  They can be organized in hierarchies, as in the following 
  1025. example: 
  1026.  
  1027. class ErrorBase{
  1028. public:
  1029.     ErrorBase(char *F,int L);
  1030.     ErrorBase(const ErrorBase &error);
  1031.     virtual ~ErrorBase();
  1032.  
  1033.     const char*     GetFile() const {return File;}
  1034.     int             GetLine() const {return Line;}
  1035.  
  1036. protected:
  1037.     char    *File;
  1038.     int     Line;
  1039. };
  1040.  
  1041. class ErrorBadArg:public ErrorBase{
  1042. public:
  1043.     ErrorBadArg(char *F,int L);
  1044.     ErrorBadArg(const ErrorBadArg &error);
  1045.     ~ErrorBadArg();
  1046.  
  1047. };
  1048.  
  1049. class ErrorNoMem:public ErrorBase{
  1050. public:
  1051.     ErrorNoMem(char *F,int L);
  1052.     ErrorNoMem(const ErrorNoMem &error);
  1053.     ~ErrorNoMem();
  1054.  
  1055. };
  1056.  
  1057. Figure 2)  Sample exception hierarchy. 
  1058.  
  1059. An advantage of using heirarchies of error objects is that any error object 
  1060. with a parent can be caught by blocks expecting the parent object.  We'll look 
  1061. at catching exceptions by the exception object's parent class later. 
  1062.  
  1063. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1064.  
  1065.  
  1066. ΓòÉΓòÉΓòÉ 6.3. Try, Catch and Throw ΓòÉΓòÉΓòÉ
  1067.  
  1068. Try, Catch and Throw 
  1069.  
  1070. "Try" blocks are used to "catch" exceptions that are thrown in functions called 
  1071. within the block.  We have already seen that an exception is nothing more than 
  1072. an object designed to convey error information.  Unlike the simple switch case, 
  1073. however, try blocks can be nested within and across function calls.  Also, 
  1074. exceptions don't rely on the function returning a value.  The following sample 
  1075. code illustrates a nested exception. 
  1076.  
  1077. void foo1(){
  1078.     try{
  1079.         foo2();
  1080.     }
  1081.     catch(ErrorBase error){
  1082.         cerr<<"An exception was thrown from file "<<error.GetFile()<<" Line "<<error.GetLine()<<endl;
  1083.     }
  1084.     catch(...){ //some other error
  1085.         cerr<<"Some other exception has been thrown"<<endl;
  1086.     }
  1087.  
  1088. }
  1089.  
  1090. void foo2(){
  1091.     try{
  1092.         foo3(10);
  1093.     }
  1094.     catch(ErrorBadArg){
  1095.         try{
  1096.             foo3(0);
  1097.         }
  1098.         catch(ErrorBadArg){
  1099.             cerr<<"I give up. 0 is not a valid arg to foo3"<<endl;
  1100.         }
  1101.         catch(ErrorNoMem){
  1102.             cerr<<"We're Out of memory"<<endl;
  1103.             throw;            //I don't want to handle this let whoever called me get a kick at it
  1104.         }
  1105.     }
  1106.     catch(ErrorNoMem){
  1107.         cerr<<"We're Out of memory"<<endl;
  1108.         throw;
  1109.     }
  1110. }
  1111.  
  1112. void foo3(int arg){
  1113.     if(arg==rand()%10)
  1114.         throw ErrorBadArg(__FILE__,__LINE__);
  1115.  
  1116.     if(arg==rand()%40)
  1117.         throw ErrorNoMem(__FILE__,__LINE__);
  1118. }
  1119.  
  1120. Figure 3)  Nested exception example. 
  1121.  
  1122. Function foo1() calls function foo2().  Any exceptions rethrown by foo2() or 
  1123. that are not handled by foo2() can be caught by foo1().  In fact, the statement 
  1124. "catch (...)" in foo1() catches all exceptions that aren't explicitly handled. 
  1125. In this case, any exception other than those in the ErrorBase() family are 
  1126. caught by the catch (...)  block.  Function foo3() illustrates how to throw an 
  1127. exception. 
  1128.  
  1129. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1130.  
  1131.  
  1132. ΓòÉΓòÉΓòÉ 6.4. Formal Exception Declaration ΓòÉΓòÉΓòÉ
  1133.  
  1134. Formal Exception Declaration 
  1135.  
  1136. In order to make sure that a function only throws certain exceptions, C++ 
  1137. allows a list of exceptions to be given with the function declaration. 
  1138. Rewriting foo3() we have: 
  1139.  
  1140. void foo3(int arg) throw(ErrorBadArg,ErrorNoMem){
  1141.     if(arg==rand()%10)
  1142.         throw ErrorBadArg(__FILE__,__LINE__);
  1143.  
  1144.     if(arg==rand()%40)
  1145.         throw ErrorNoMem(__FILE__,__LINE__);
  1146. }
  1147.  
  1148. Figure 4)  Declaring a method to throw specific exception classes. 
  1149.  
  1150. Now foo3() can only throw the exceptions ErrorBadArg and ErrorNoMem.  An 
  1151. attempt to throw any other exception will result in a runtime error.  This 
  1152. makes it easier for the programmer to use third party libraries.  The program 
  1153. will not encounter any surprise exceptions because the set of exceptions which 
  1154. a routine may throw is guaranteed. 
  1155.  
  1156. Note:  foo3() must catch all exceptions in any routine it calls other than the 
  1157. two it declares as those to be thrown by it. 
  1158.  
  1159. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1160.  
  1161.  
  1162. ΓòÉΓòÉΓòÉ 6.5. Runtime Exception Errors ΓòÉΓòÉΓòÉ
  1163.  
  1164. Runtime Exception Errors 
  1165.  
  1166. There's two runtime errors that can occur in the exception handling code. 
  1167. First, the exception might not be caught by any try/catch block.  Second, an 
  1168. exception that wasn't in the declaration list for a function might not be 
  1169. caught by the function or a programmer may try to throw an unlisted exception. 
  1170. In the first case, the "terminate" function is called, in the second, the 
  1171. "unexpected" function is called.  The functions set_terminate() and 
  1172. set_unexpected() can be used to replace the default function with application 
  1173. specific ones.  The following sample shows how to use set_terminate(). 
  1174.  
  1175. typedef void (*pVdFn)();
  1176.  
  1177. void My_Terminate(){
  1178.     cerr<<"My Terminate Called"<<endl;
  1179.     exit(1);
  1180. }
  1181.  
  1182. int main(){
  1183.     pVdFn oldFn=set_terminate(My_Terminate);    //replace the previous terminate fnc
  1184.  
  1185.     foo3(11);
  1186.  
  1187.     set_terminate(oldFn);                       //set the terminate fnc back to the original
  1188.  
  1189.     /* do other stuff here */
  1190.  
  1191. return 0;
  1192. }
  1193.  
  1194. Figure 5)  Using set_terminate(). 
  1195.  
  1196. In the above sample, if an exception occurs in foo3(), My_Terminate() should be 
  1197. called because we didn't set up a catch/try block. 
  1198.  
  1199. Note:  set_unexpected() is used in the exact same way as set_terminate(). 
  1200.  
  1201. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1202.  
  1203.  
  1204. ΓòÉΓòÉΓòÉ 6.6. Gotchas ΓòÉΓòÉΓòÉ
  1205.  
  1206. Gotchas 
  1207.  
  1208. There are two areas to watch out for.  The first one is resource leaks. The 
  1209. second one is an overreliance on exceptions to alter the programs flow. Let's 
  1210. look at the following sample function. 
  1211.  
  1212. void foobar(char *arg){
  1213.     char    *X=new char[300];
  1214.  
  1215.     DosRequestMutexSem(hMux,-1);
  1216.     if(arg==NULL)
  1217.         throw ErrorBadArg;
  1218.  
  1219.  
  1220.     DosReleaseMutexSem(hMux);
  1221.     delete [] X;
  1222. }
  1223.  
  1224. Figure 6)  Resource leaks with thrown exceptions. 
  1225.  
  1226. There are 2 potential resource leaks in this function.  Because the throw 
  1227. alters the programs flow, when the throw statement is executed the mutex 
  1228. semaphore will not be released and the allocated memory will not be returned to 
  1229. the heap.  There are several different ways of fixing this problem.  The 
  1230. easiest is to move the allocation and semaphore request to after then throw 
  1231. statement. 
  1232.  
  1233. void foobar(char *arg){
  1234.     if(arg==NULL)
  1235.         throw ErrorBadArg;
  1236.  
  1237.     char    *X=new char[300];
  1238.  
  1239.     DosRequestMutexSem(hMux,-1);
  1240.  
  1241.  
  1242.     DosReleaseMutexSem(hMux);
  1243.     delete [] X;
  1244. }
  1245.  
  1246. Figure 7)  Removing the leak by relocating the resource allocation. 
  1247.  
  1248. Another approach would be to release the semaphore and free the memory before 
  1249. throwing the exception. 
  1250.  
  1251. void foobar(char *arg){
  1252.     char    *X=new char[300];
  1253.  
  1254.     DosRequestMutexSem(hMux,-1);
  1255.  
  1256.     if(arg==NULL){
  1257.         DosReleaseMutexSem(hMux);
  1258.         delete [] X;
  1259.  
  1260.         throw ErrorBadArg;
  1261.     }
  1262.  
  1263.     DosReleaseMutexSem(hMux);
  1264.     delete [] X;
  1265. }
  1266.  
  1267. Figure 8)  Removing the leak by freeing the resource before throwing an 
  1268. exception. 
  1269.  
  1270. Finally, the most thorough way is to use objects to handle the memory and 
  1271. semaphore. 
  1272.  
  1273. template<class T> class MemBlock{
  1274.     typedef T *pT;
  1275. public:
  1276.     MemBlock(size_t len){Block=new T[len];}
  1277.     ~MemBlock(){if(Block!=NULL) delete [] MemBlock;}
  1278.  
  1279.     operator pT(){return Block;}
  1280.  
  1281. protected:
  1282.     pT  Block;
  1283. };
  1284.  
  1285. class MutexRequest{
  1286.     typedef unsigned long ULONG;
  1287.     typedef unsigned long HMTX;
  1288. public:
  1289.     MutexRequest(HMTX hand,ULONG time){hmtx=hand;DosRequestMutexSem(hmtx,time);}
  1290.     ~MutexRequest(){DosReleaseMutexSem(hmtx);}
  1291.  
  1292. protected:
  1293.     HMTX    hmtx;
  1294. };
  1295.  
  1296. void foobar(char *arg){
  1297.     MemBlock<char>  X(300);
  1298.     MutexRequest    sem(hMux,-1);
  1299.  
  1300.  
  1301.     if(arg==NULL)
  1302.         throw ErrorBadArg;
  1303.  
  1304.     /* do other stuff here */
  1305. }
  1306.  
  1307. Figure 9)  Removing the leak by performing resource management in the 
  1308. constructor and destructor. 
  1309.  
  1310. This last approach has a hidden advantage.  Suppose we called some other 
  1311. functions in foobar() and one of these functions threw an exception.  What 
  1312. would happen in either of our first 2 versions of foobar()?  The answer is that 
  1313. we would have the same resource leak that we fixed in the last 2 versions. 
  1314. Unless we add a try/catch block in foobar() and then place calls to 
  1315. DosReleaseMutexSem() and delete inside the catch block, we will leak resources. 
  1316. Encapsulating the resources and using constructors/destructors to handle their 
  1317. allocation and deallocation provides a safer alternative than manually 
  1318. maintaining the deallocation of resources in several possible exit points. 
  1319.  
  1320. The second pitfall is using exceptions too liberally.  Suppose we have a 
  1321. function that has a fixed set of valid results.  Let's say that one result 
  1322. happen most of the time, but it is possible in some cases for the others to 
  1323. occur.  Should we use exceptions?  The answer is no.  Exceptions should only be 
  1324. used to indicate error conditions, not to indicate which action a function 
  1325. performed.  As we seen from the C++ compiler benchmarks several issues ago, 
  1326. throwing exceptions is expensive.  Not only is throwing the exception 
  1327. expensive, but setting up a try block alone can have noticeable overhead.  To 
  1328. keep performance acceptable, exceptions should only be used to indicate an 
  1329. error condition. 
  1330.  
  1331. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1332.  
  1333.  
  1334. ΓòÉΓòÉΓòÉ 6.7. Wrapping Things Up ΓòÉΓòÉΓòÉ
  1335.  
  1336. Wrapping Things Up 
  1337.  
  1338. This concludes our look at C++ exception handling.  We covered how to define 
  1339. exceptions, catching, and throwing exceptions.  Also, we seen how to handle 
  1340. unexpected results by using the set_terminate() and set_unexpected() functions. 
  1341. Exceptions provide a formal method for handling and declaring error conditions. 
  1342. They have significant run time cost and should only be used where necessary. 
  1343.  
  1344. OOPS Avenue - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1345.  
  1346.  
  1347. ΓòÉΓòÉΓòÉ 7. REXX Inside and Out ΓòÉΓòÉΓòÉ
  1348.  
  1349.  
  1350. ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
  1351.  
  1352. Rexx Inside and Out 
  1353.  
  1354. Written by Joy Wyatt 
  1355.  
  1356. Introduction 
  1357.  
  1358. When Rexx was originally written for IBM's Virtual Machine operating system, it 
  1359. was given no native file handling capabilities.  VM has its own file handling 
  1360. command, EXECIO, which has proven to be sufficient in that environment.  There 
  1361. is a down side to everything and the problem with EXECIO is that it is part of 
  1362. VM and not an architected element of the Rexx language. When portability became 
  1363. an issue, Mike Cowlishaw, author of Rexx, went back to the drawing board and 
  1364. designed enhancements to the language that allow Rexx programs to read and 
  1365. write to files in such a way as to be independent of the operating platform. 
  1366. This article will take a look at each of Rexx's file handling functions to 
  1367. perform the basics of file manipulation. 
  1368.  
  1369. "So what, Uncle Bob, are the basics", you ask?  Well, boys and girls, quit 
  1370. calling me Uncle Bob and we'll get on with it.  Rudimentary file function 
  1371. includes opening a file, writing to it, reading from it, and closing it. There 
  1372. is more than one way to do each of these and we will discuss all of the ones I 
  1373. know about, their good points, and their bad.  Before we get into the nitty 
  1374. gritty we must get a definition behind us. 
  1375.  
  1376. file pointer:  A file pointer is a place holder the operating system uses to 
  1377. keep track of where the program is reading or writing in a file.  Let's use a 
  1378. small file as an example to provide an illustrative definition.  Imagine the 
  1379. file as 512 characters typed onto a page.  Take your finger and point to the 
  1380. first character on the page.  Read the character under your finger and move 
  1381. your finger to the next character.  Your finger on the page is like the file 
  1382. pointer OS/2 uses.  When you tell OS/2 to read a line or a character from a 
  1383. file, OS/2 moves its "finger" to the next line or character to be read. 
  1384. Although OS/2 doesn't really have any fingers it does have a better imagination 
  1385. than you do. 
  1386.  
  1387. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1388.  
  1389.  
  1390. ΓòÉΓòÉΓòÉ 7.2. Opening a file ΓòÉΓòÉΓòÉ
  1391.  
  1392. Opening a file 
  1393.  
  1394. While Rexx does not contain a specific "open file" function, there are at least 
  1395. five methods of opening a file on purpose (explicitly as opposed to 
  1396. implicitly).  The first four are easy to explain away. 
  1397.  
  1398. Any attempt to write to an unopened file using the lineout or charout functions 
  1399. will implicitly attempt to open the file for read/write processing. These 
  1400. functions can also be used to explicitly open a file.  The following 
  1401. statements: 
  1402.  
  1403. /* open file and place file pointer on line 1 */
  1404. rc = lineout( myFile, , 1 );
  1405. rc = charout( myFile, , 1);
  1406.  
  1407. Figure 1)  Implicitly opening a file for read/write access. 
  1408.  
  1409. will attempt to open the file whose name is contained in the variable myFile. 
  1410. If the open process is successful the value of rc will be "0" and the file 
  1411. pointer will be positioned at the beginning of the existing file.  If, for some 
  1412. reason, the file cannot be opened rc's value will be "1".  While this is 
  1413. functional, it generally leads to such descriptive error messages as, "Hey, 
  1414. Hoser!  Your file just ain't going to make it this time."  This isn't a lot of 
  1415. debug information to go on.  The input functions are similar in that the first 
  1416. use of them on an unopened file will implicitly attempt to open the file. They 
  1417. also may be used for an explicit open as follows: 
  1418.  
  1419. /* open file and read zero lines from line 1 */
  1420. rc = linein( myFile, 1, 0 );
  1421.  
  1422. /* open file and read zero chars from char 1 */
  1423. rc = charin( myFile, 1, 0);
  1424.  
  1425. Figure 2)  Implicitly opening a file for read-only access. 
  1426.  
  1427. When either of these functions, used in this manner, are successful the file 
  1428. pointer is placed at the first character of the file.  As far as diagnostic 
  1429. information is concerned these input functions are worse than their output 
  1430. siblings.  These functions return data and no numeric code.  If everything went 
  1431. well there is no return data from the function because of the "0" in the 
  1432. parameter list.  If the file could not be opened then there is no return data 
  1433. from the function.  This leads to error messages similar to, "Hey, Hoser.  If 
  1434. you got this message then there were no syntax errors in the open call, but we 
  1435. don't know if your file opened successfully." 
  1436.  
  1437. "Alas!", you cry.  "Are users of my Rexx code destined to be called 'Hosers' 
  1438. for the rest of their days?" 
  1439.  
  1440. Maybe.  But you can at least give them some decent debugging information as 
  1441. well by using the stream function to open your files. 
  1442.  
  1443. The stream function is multipurpose and can handle the opening of files very 
  1444. nicely.  Stream has other uses, but this article will not delve into them.  We 
  1445. will limit ourselves to using stream to open and close files.  The following 
  1446. invocation of stream: 
  1447.  
  1448. rc = stream( myFile, "c", "open" );
  1449.  
  1450. Figure 3)  Explicitly opening a file. 
  1451.  
  1452. will attempt to open the file for reading and writing and place something a bit 
  1453. more usable in the return area if the attempt fails. 
  1454.  
  1455. Should the file be opened successfully the string "READY:"  is stored in your 
  1456. result area.  If there are problems, however, a string similar to "NOTREADY:nn" 
  1457. is issued.  The "nn" in this case is a return code that indicates the reason 
  1458. the attempt to open the file failed.  This code can be used with OS/2's help 
  1459. facility to provide the user with some valuable information.  See example code 
  1460. Rexx_a.cmd for an illustration. 
  1461.  
  1462. The stream function can also be used to open a file and designate its intended 
  1463. use.  This allows you to set the file pointer for the processing you desire. 
  1464. The default open mode is "read" which will place the file pointer at the first 
  1465. byte of the file.  Changing the third parameter from "open" to "open write" 
  1466. will cause the file pointer to be placed at the end of the file.  "Open read" 
  1467. as the third parameter will set the file pointer to the top of the file and 
  1468. limit the function to read only. 
  1469.  
  1470. Most of the Rexx programs that I have seen, though, do not use any of these 
  1471. explicit methods for opening a file for processing.  If the two terms "quick 
  1472. and dirty" and "Rexx programming" seem synonymous to you then you may already 
  1473. be aware that the first use of any of the input/output functions will 
  1474. implicitly attempt to open the file.  You still, of course, are limited to the 
  1475. eloquent "1" or "0" diagnostics with this method. 
  1476.  
  1477. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1478.  
  1479.  
  1480. ΓòÉΓòÉΓòÉ 7.3. Reading Data From a File ΓòÉΓòÉΓòÉ
  1481.  
  1482. Reading Data From a File 
  1483.  
  1484. Unlike open, you cannot read (or write) data by accident.  Two built-in methods 
  1485. for reading data exist in the Rexx language.  The "C" programmer in me was 
  1486. fairly comfortable dealing with the "one character at a time" functionality of 
  1487. the charin function, but the rich string handling functions in Rexx have caused 
  1488. me to all but abandon charin. 
  1489.  
  1490. Charin 
  1491.  
  1492. Charin reads one or more characters at a time from a specified location and 
  1493. returns the data to the result area.  It is quite handy when there are no CR LF 
  1494. defined records in the file to be read or when a specified block length is 
  1495. needed, but that is usually a contrived situation on the PC platform.  To test 
  1496. the performance, I created a file with 1024 records of 1024 bytes each and read 
  1497. them using both charin and linein.  Detailed results are located in a table 
  1498. after the linein discussion. 
  1499.  
  1500. Syntax of the charin function: 
  1501.  
  1502. text = charin(myFile, start, count);
  1503.  
  1504. Figure 4)  Syntax of charin. 
  1505.  
  1506. To make things interesting none of the parameters are required.  If myFile is 
  1507. not specified then the data is taken from the standard input device (usually 
  1508. the keyboard).  The second parameter, start, positions the file pointer before 
  1509. the read takes place.  The final parameter, count, specifies the number of 
  1510. characters that are to be read.  So to read eight characters starting at the 
  1511. 50th character, the function would be coded as follows: 
  1512.  
  1513. text = charin(myFile, 50, 8);
  1514.  
  1515. Figure 5)  Using charin to read a specific set of characters in a file. 
  1516.  
  1517. That's about all there is to it.  An example of the use of charin is included 
  1518. as Rexx_b.cmd.  This program does a hex dump of itself.  Not very useful, I 
  1519. agree, but you are welcome to customize the program for your own uses. 
  1520.  
  1521. Linein 
  1522.  
  1523. The Rexx language is a string manipulator's dream language (relative to C, 
  1524. PL/1, FORTRAN, Pascal, or COBOL).  Because of this it is quite nice to consider 
  1525. an entire line at one time.  This is achieved with the linein function. 
  1526. Linein's syntax: 
  1527.  
  1528. record = linein(myFile, start, count);
  1529.  
  1530. Figure 6)  Syntax of linein. 
  1531.  
  1532. It would follow that the parameters act just like those of charin.  They don't. 
  1533. MyFile still contains the name of the file to be read, and defaults to the 
  1534. standard input if not specified.  Start specifies the line you wish to place 
  1535. the file pointer on before the read is done.  OS/2 only allows a start value of 
  1536. 1, the beginning of the file.  Count is still the number of lines to read, but 
  1537. the only valid values are "1" and "0". 
  1538.  
  1539. So which function is best to perform a read?  It depends.  If you are 
  1540. performing random reads of files with constant record sizes then you might want 
  1541. to use charin because of its ability to position the file pointer.  If there 
  1542. are variable length records in the file and the program considers a record at a 
  1543. time during processing it makes sense to use linein.  There is usually a design 
  1544. consideration that makes one of these functions better than the other.  It is a 
  1545. good knowledge of how each one works that gives the programmer the power to 
  1546. make that decision. 
  1547.  
  1548. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1549. Γöé                    Γöélinein              Γöécharin              Γöé
  1550. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1551. Γöé1 byte/read         Γöén/a                 Γöé705.94 secs         Γöé
  1552. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1553. Γöé1K bytes/read       Γöé3.7 secs            Γöé1.65 secs           Γöé
  1554. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1555. Γöé1M bytes/read       Γöén/a                 Γöé2.6 secs            Γöé
  1556. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1557.  
  1558. Table 1)  Comparison of the performance of linein and charin by the number of 
  1559. characters handled when reading file with 1024 records of 1024 bytes each. 
  1560. Cache was cleared between each test. 
  1561.  
  1562. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1563.  
  1564.  
  1565. ΓòÉΓòÉΓòÉ 7.4. Writing to a File ΓòÉΓòÉΓòÉ
  1566.  
  1567. Writing to a File 
  1568.  
  1569. Each of the input functions described above, charin and linein, have twins for 
  1570. writing data to a file.  These functions are fairly consistent with their 
  1571. sibling input functions, but there is a difference when these functions are 
  1572. used to open the file implicitly.  If charout or lineout are used the file is 
  1573. opened for write, the file pointer is positioned at the end file, and the data 
  1574. to be written is appended to the file. 
  1575.  
  1576. Charout 
  1577.  
  1578. Charout will place a string into a specified file starting at any location 
  1579. within the file that the programmer desires.  No carriage return/line feed 
  1580. combination is inserted after the data. 
  1581.  
  1582. count = charout(myFile, text, start);
  1583.  
  1584. Figure 7)  Syntax of charout. 
  1585.  
  1586. This function call looks much like charin with text, start, and count shifted. 
  1587. Text is the string to be written to the file.  String can contain non-printable 
  1588. characters (including carriage returns and line feeds).  Start, again, is the 
  1589. position of the file pointer before the read.  The desired value of count is 0. 
  1590.  
  1591. Count does not indicate the number of bytes successfully written to the file, 
  1592. but indicates the number of bytes not written to the file because of some type 
  1593. of error. 
  1594.  
  1595. Lineout 
  1596.  
  1597. While charout could be used several times during the output of a single record, 
  1598. lineout will always append the text with an end of record marker. This requires 
  1599. the programmer to build all data for the record in a program variable.  Lineout 
  1600. looks quite similar to its cousin, charout. 
  1601.  
  1602. count = lineout(myFile, text, start);
  1603.  
  1604. Figure 8)  Syntax of lineout. 
  1605.  
  1606. The parameters and return values are the same as charout except that they deal 
  1607. with lines rather than characters.  The only valid value of start is "1". This 
  1608. will set the file pointer to the beginning of the file and existing text will 
  1609. be overwritten.  Omit the parameter to continue writing where the file pointer 
  1610. currently resides. 
  1611.  
  1612. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1613.  
  1614.  
  1615. ΓòÉΓòÉΓòÉ 7.5. Closing the File ΓòÉΓòÉΓòÉ
  1616.  
  1617. Closing the File 
  1618.  
  1619. Either of the output functions may be used to close the file by supplying only 
  1620. the file name as an argument. 
  1621.  
  1622. lineout( myFile );
  1623. charout( myFile );
  1624.  
  1625. Figure 9)  Implicitly closing a file. 
  1626.  
  1627. Either of the two functions will suffice.  However, and there is always a 
  1628. however, if the close should fail there is no indication of this fact nor the 
  1629. reasons for its occurrence.  The stream function should be used for programs 
  1630. other than personal utilities to close the file as well as open it. 
  1631.  
  1632. rc = stream(myFile, "c", "close");
  1633.  
  1634. Figure 10)  Explicitly closing a file. 
  1635.  
  1636. The above invocation should look familiar.  The diagnostics are not as 
  1637. descriptive for close as they are for open, but at least there is an indication 
  1638. of the success of the call.  Should the close command fail, the stream function 
  1639. will return a null string.  The literal "READY:"  is returned after a 
  1640. successful close. 
  1641.  
  1642. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1643.  
  1644.  
  1645. ΓòÉΓòÉΓòÉ 7.6. Other File Functions of Note ΓòÉΓòÉΓòÉ
  1646.  
  1647. Other File Functions of Note 
  1648.  
  1649. Reading data from a file is fine and good, but it would be nice to know when to 
  1650. stop reading.  I'll quickly outline two functions that exist for this purpose. 
  1651.  
  1652. Chars 
  1653.  
  1654. Chars is a function that will return the number of characters from the current 
  1655. location of a file pointer to the end of the file.  This function can be used 
  1656. with the character based input function, charin, to calculate the number of 
  1657. times a loop needs to be iterated to read the entire file.  It is suggested 
  1658. that chars be called once before the loop to calculate a constant value for the 
  1659. loop comparison rather than calling the function in the loop. Chars only 
  1660. accepts one argument. 
  1661.  
  1662. count = chars( myFile );
  1663.  
  1664. Figure 11)  Syntax of chars. 
  1665.  
  1666. The above invocation will return the number of bytes from the current location 
  1667. of the file pointer to the end of myFile.  Execution of this function against 
  1668. any defined OS/2 device, such as LPT1:, will always return "1". Chars cousin is 
  1669. lines. 
  1670.  
  1671. Lines 
  1672.  
  1673. You might think that the lines function would return the number of lines from 
  1674. the file pointer to the end of the file.  You might have caught on by now that 
  1675. OS/2 has no idea how many lines there are from the current file pointer to the 
  1676. end of the file.  Since there is no constant record structure in an OS/2 file 
  1677. the lines function simply returns a "1" if there are remaining lines to be 
  1678. read.  This means that you cannot use lines to calculate a constant number of 
  1679. times to process a loop, but must use the function in the loop comparison. 
  1680.  
  1681. do while( lines( myFile ) )
  1682.    rec = linein( myFile )
  1683. end
  1684.  
  1685. Figure 12)  Using lines in a loop. 
  1686.  
  1687. This snippet of useless code will read all of the data in myFile and stop at 
  1688. the end of file.  The body of the loop should be customized to actually perform 
  1689. some useful work. 
  1690.  
  1691. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1692.  
  1693.  
  1694. ΓòÉΓòÉΓòÉ 7.7. That's the Basics ΓòÉΓòÉΓòÉ
  1695.  
  1696. That's the Basics 
  1697.  
  1698. You can't get much more basic than open, close, read, and write.  There is more 
  1699. than one way to do each of these.  The correct way depends on the context of 
  1700. your program and its intended audience.  The important point is that your 
  1701. understanding of the available functions is key to your choosing the best 
  1702. method to fit the program's circumstances. 
  1703.  
  1704. More (and probably better) information can be obtained from OS/2's online Rexx 
  1705. manual.  If you would like to comment on or contest any of this information 
  1706. please feel free to do so.  My email address is in the "Contributors" section. 
  1707.  
  1708. Rexx Inside and Out - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1709.  
  1710.  
  1711. ΓòÉΓòÉΓòÉ 8. Under the Scope ΓòÉΓòÉΓòÉ
  1712.  
  1713.  
  1714. ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
  1715.  
  1716. Under the Scope 
  1717.  
  1718. Written by Brad Scharf 
  1719.  
  1720. Introduction 
  1721.  
  1722. Welcome to the utility review column.  This is a new column that will review 
  1723. freeware, shareware and commercially available applications intended to aid the 
  1724. development process and initially will be targeted towards beginner OS/2 
  1725. programmers. 
  1726.  
  1727. The column will feature one or two utilities each month.  I will try and let 
  1728. the reader know in advance which tools will be featured.  Also, there will be 
  1729. an index at the end of every column that will include program names and 
  1730. descriptions, which issue of EDM/2 featured the program review and in future 
  1731. issues I will try and let the reader know where the utilities can be found and 
  1732. at what cost. 
  1733.  
  1734. By the way, if you have any comments or suggestions regarding this column 
  1735. please let me know.  If the column is to be a success it will be through the 
  1736. feedback of its readers.  Likewise, if you know of a utility that would be 
  1737. beneficial to other programmers please mention it and I'll do what I can to 
  1738. ensure that readers are made aware of it.  I may be reached via the internet at 
  1739. schab@sasknet.sk.ca . 
  1740.  
  1741. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1742.  
  1743.  
  1744. ΓòÉΓòÉΓòÉ 8.2. What's Reviewed ΓòÉΓòÉΓòÉ
  1745.  
  1746. What's Reviewed 
  1747.  
  1748. In my own experience, and I imagine most of your own, I have found that despite 
  1749. my best intentions my programs don't always behave as expected.  (That must be 
  1750. a first!)  Usually this isn't a problem but occasionally I'll compile and run a 
  1751. program which I then can't shutdown, even from the Window List. 
  1752.  
  1753. In addition to the above, sometimes we will write applications that modify 
  1754. system INI files.  It's a sad fact of life that the modifications will not 
  1755. always be as expected, or perhaps we just wish to remove them in order to leave 
  1756. things as they were before testing our projects. 
  1757.  
  1758. To help us deal with both of these issues, I review in this issue a process 
  1759. monitor utility entitled PSPM/2, as well as an INI file editor called EDITINI. 
  1760. So read on! 
  1761.  
  1762. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1763.  
  1764.  
  1765. ΓòÉΓòÉΓòÉ 8.3. PSTAT PM/2 v5.10 ΓòÉΓòÉΓòÉ
  1766.  
  1767. PSTAT PM/2 v5.10 
  1768.  
  1769. PSTAT PM/2 (PSPM/2) is a 32-bit PM utility that provides the user with a 
  1770. graphical representation of running processes as well as information about 
  1771. those processes, such as hierarchical relationships, number of threads and 
  1772. thread info. 
  1773.  
  1774. All of the information that can be obtained from this program is available from 
  1775. the PSTAT program that ships with OS/2.  In fact, PSTAT will actually provide 
  1776. more information than PSPM/2.  The usefulness of PSPM/2 lies in its ease of 
  1777. use, simple visual representation of running processes, point-and-shoot 
  1778. capabilities, continual refresh (if desired) and perhaps most of all, the 
  1779. ability to terminate running processes.  Unlike some other process killers, 
  1780. PSPM/2 works independently from OS/2s PSTAT program. 
  1781.  
  1782. The need for this type of utility first became apparent to me when, after 
  1783. writing my first PM program, I could not stop it from running.  The appearance 
  1784. program icon indicated that it was running but nothing appeared on the screen, 
  1785. nor did the program appear in the window list.  The only method available to 
  1786. shut down the application was to reboot my PC.  Obviously this is not the 
  1787. preferred method of shutting down applications!.  As it turned out, I had 
  1788. declared the window to include a menu item that I failed to provide in a 
  1789. resource file.  Everything compiled OK but the system didn't like it very much. 
  1790. In comes PSPM/2... 
  1791.  
  1792. In cases as I've mentioned PSPM/2 performs very well.  It allows one to obtain 
  1793. basic information about a running process and to shut the process down if 
  1794. desired.  Of the many times I've used it to do this I have never found any 
  1795. problems.  Shutting down an application is simply a matter of clicking on the 
  1796. process name in the main window and selecting "Terminate Process" from the 
  1797. resulting dialog.  At this point you have one chance to change your mind when 
  1798. the verification dialog appears.  Selecting "Yes" will terminate the process. 
  1799.  
  1800. Where PSPM/2 does not perform well is during cases of system lockup.  Since the 
  1801. program only responds to user requests, it relies on keyboard and/or mouse 
  1802. input.  This renders the program useless when user I/O is not possible.  As a 
  1803. result, if your new programs locks up the system you need to reboot or make use 
  1804. of a different utility that allows you to recover from these situations if 
  1805. repeated pressing of Ctrl-Esc doesn't work. 
  1806.  
  1807. Another situation where PSPM/2 can cause problems occurs when it is used (at 
  1808. least on my system) to shut down PMSHELL in an attempt to reboot the Workplace 
  1809. Shell.  This caused a blank desktop to appear with a loss of keyboard and mouse 
  1810. response and required a reboot of my system.  Its effect on other WPS 
  1811. applications is unknown and would require further testing to determine its 
  1812. suitability for closing misbehaved WPS programs that you may be writing. Since 
  1813. OS/2 can behave quite differently with individual installations other users may 
  1814. get different results and if so I would be interested in hearing about them. 
  1815.  
  1816. Configuration of PSPM/2 is very simple.  The user has one pull- down menu from 
  1817. which settings such as default font, window position and size, colours and 
  1818. refresh rate may be selected.  The settings may be changed for a single session 
  1819. only by declining to save the selected options.  There is no online help but 
  1820. everything is pretty straight-forward so the lack of built-in documentation 
  1821. should not pose problems. 
  1822.  
  1823. Overall, PSPM/2 is a nice little utility.  The graphical, tree-like display 
  1824. provides an easy and quick way to view which processes are running.  Viewing 
  1825. information about or termination of a process is simply a matter of clicking on 
  1826. the process name.  As a programming aid, it has saved me much time by allowing 
  1827. me to close test applications by eliminating the need to reboot. While not the 
  1828. only utility of this type, it is a simple and effective tool well worth the 
  1829. storage space it takes up on your disk. 
  1830.  
  1831. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1832.  
  1833.  
  1834. ΓòÉΓòÉΓòÉ 8.4. EditINI ΓòÉΓòÉΓòÉ
  1835.  
  1836. EditINI 
  1837.  
  1838. EditINI is a simple tool that may be useful to those who create programs that 
  1839. modify either the OS2.INI or OS2SYS.INI files.  Being even less complex than 
  1840. PSPM/2 this review will be short. 
  1841.  
  1842. EditINI allows the user to view, add, modify or delete information from the OS2 
  1843. and OS2SYS INI files.  The PM interface makes it easy to use.  You select which 
  1844. of the INI files you wish use from one of two radio buttons, pick the 
  1845. application (from a drop down list-box) whose entries you wish to act upon, 
  1846. choose the "key name" (also from a list box) and view or modify the data under 
  1847. that key name. 
  1848.  
  1849. This isn't a bad little utility if your applications make few modifications to 
  1850. the INI files, but for programs that make lots of additions to these files, 
  1851. EditINI, while still useful, can be time-consuming.  There can (and probably 
  1852. will) be dozens of application entries and each application in turn can have 
  1853. many more entries in the "key names" and data fields.  This isn't a problem 
  1854. when manually changing settings in the INI files, but can be time consuming 
  1855. when deleting all references to a program because the list boxes are of the 
  1856. style "single selection". 
  1857.  
  1858. To make matters worse, after deleting an entry, the lists are reset to the top. 
  1859. Applications can only be deleted by first removing all "key names" (one at a 
  1860. time) and if an application has made many entries into the INI files it may 
  1861. take a while to remove all references to it because you have to find (again) 
  1862. the application name and then the key name from lists that can be fairly long. 
  1863.  
  1864. If your program does make lots of entries, it may be best to create a separate 
  1865. INI file for use during the testing phase of development and then, when 
  1866. everything has been debugged, simply change the code to use the system INI 
  1867. files instead of an application-specific one.  This won't work in all cases, as 
  1868. you may need to register new objects or data types etc., but placing as many 
  1869. profile items as possible into a separate file during development can save a 
  1870. lot of time.  This way, if things don't go as they should, you can simply 
  1871. delete the new INI file and try again.  As you can probably tell from this 
  1872. text, I'm a firm believer in the hit-and-miss approach!. 
  1873.  
  1874. Where this program can be really convenient is when writing your first 
  1875. applications that read and write to the INI files.  Since we all know it's 
  1876. safer to read from than to write to a file, you can use EditINI to make INI 
  1877. file entries manually, perfect the code that reads the information first and 
  1878. then worry about the code that writes information.  For beginners this is ideal 
  1879. because it allows one to get some experience with the profile functions without 
  1880. the worry of destroying important system files.  For the more advanced user, 
  1881. any information contained in the OS2 and OS2SYS INI files can be viewed, 
  1882. modified or deleted.  Since there are too many to list, I'll assume you know 
  1883. what INI entries you need to access but rest assured that if it exists in these 
  1884. files, you can get at it with EditINI. 
  1885.  
  1886. Despite having mentioned more dislikes than likes about this program, I do like 
  1887. it and would have had more good things to say if it weren't so simplistic.  As 
  1888. a tool, especially for beginners, it is very useful and should be part of your 
  1889. collection. 
  1890.  
  1891. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1892.  
  1893.  
  1894. ΓòÉΓòÉΓòÉ 8.5. Index ΓòÉΓòÉΓòÉ
  1895.  
  1896. Index 
  1897.  
  1898. This index is intended to give you an overview of the products reviewed and 
  1899. will eventually contain other pertinent information such as an overall rating 
  1900. and a brief summary of the product reviewed.  Each table is assigned a category 
  1901. and contains products which fall into that category; however, as more products 
  1902. are reviewed, the category list will be expanded and some categories might be 
  1903. renamed to more accurately reflect their contents. 
  1904.  
  1905. System Information Utilities 
  1906.  
  1907. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1908. ΓöéProgram             ΓöéIssue     Γöé
  1909. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1910. ΓöéPSPM/2              Γöé4-1       Γöé
  1911. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1912.  
  1913. INI File Editors 
  1914.  
  1915. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1916. ΓöéProgram             ΓöéIssue     Γöé
  1917. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1918. ΓöéEditINI             Γöé4-1       Γöé
  1919. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1920.  
  1921. Under the Scope - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1922.  
  1923.  
  1924. ΓòÉΓòÉΓòÉ 9. Contributors to this Issue ΓòÉΓòÉΓòÉ
  1925.  
  1926. Are You a Potential Author? 
  1927.  
  1928. We are always looking for authors.  If you have a topic about which you would 
  1929. like to write, send a brief description of the topic electronically to any of 
  1930. the editors by the 15th of the month before the month in which your article 
  1931. will appear.  This alerts us that you will be sending an article so that we can 
  1932. plan the issue layout accordingly. 
  1933.  
  1934. After you have done this, read the latest copy of the Article Submission 
  1935. Guidelines on our web site or download them to your machine also from our web 
  1936. site.  These guidelines contain everything you need to know about writing an 
  1937. article for EDM/2. 
  1938.  
  1939. The editors can be reached at the following email addresses: 
  1940.  
  1941.      Larry Salomon - larry_salomon@iqpac.com (Internet). 
  1942.      Carsten Whimster - carsten_whimster@iqpac.com (Internet). 
  1943.  
  1944.  The following people contributed to this issue in one form or another (in 
  1945.  alphabetical order): 
  1946.  
  1947.      Edward Boykin 
  1948.      Larry Salomon, Jr. 
  1949.      Brad Scharf 
  1950.      Carsten Whimster 
  1951.      Joe Wyatt 
  1952.      Gordon Zeglinski 
  1953.      Network distributors 
  1954.  
  1955.  Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1956.  
  1957.  
  1958. ΓòÉΓòÉΓòÉ 9.1. Edward Boykin ΓòÉΓòÉΓòÉ
  1959.  
  1960. Edward Boykin 
  1961.  
  1962. Ed Boykin will graduate this winter from Georgia Institute of Technology with a 
  1963. Bachelors' Degree in Aerospace Engineering.  He has been studying programming 
  1964. on his own for about three years and will probably be continuing at Tech to get 
  1965. a Master's degree in Computer Science or Engineering.  His current OS/2 
  1966. projects include a POP and SMTP e-mail program for OS/2 and other network 
  1967. client/server projects.  He is currently working as an intern for Racetrac 
  1968. Petroleum Corp.  doing client/server programming using Microsoft Windows NT and 
  1969. Oracle. 
  1970.  
  1971. He can be reached at aviator@mindspring.com or on the IRC #OS/2 channel as Av8| 
  1972.  
  1973. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1974.  
  1975.  
  1976. ΓòÉΓòÉΓòÉ 9.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  1977.  
  1978. Larry Salomon Jr. 
  1979.  
  1980. Larry Salomon Jr.  has been developing OS/2 applications since version 1.1 in 
  1981. 1989.  He has written numerous applications, including the Scramble applet that 
  1982. was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen 
  1983. Capture trio that has been distributed on numerous CD-ROMs. 
  1984.  
  1985. Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C 
  1986. Programming (Wiley-QED).  Finally, he is the CEO/President of IQPac Inc.  which 
  1987. is responsible for the publication of EDM/2, and he is a frequent contributor 
  1988. to the publication. 
  1989.  
  1990. Larry can be reached electronically via the Internet at 
  1991. larry_salomon@iqpac.com. 
  1992.  
  1993. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  1994.  
  1995.  
  1996. ΓòÉΓòÉΓòÉ 9.3. Brad Scharf ΓòÉΓòÉΓòÉ
  1997.  
  1998. Brad Scharf 
  1999.  
  2000. Brad discovered computers while enrolled in a chemistry B.S. program and soon 
  2001. after switched to computer science.  He has been using OS/2 since the release 
  2002. of version 2.0, has used OS/2 exclusively since version 2.1, and is now in the 
  2003. process of teaching himself PM programming. 
  2004.  
  2005. Brad can be reached via the internet at schab@sasknet.sk.ca 
  2006.  
  2007. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  2008.  
  2009.  
  2010. ΓòÉΓòÉΓòÉ 9.4. Carsten Whimster ΓòÉΓòÉΓòÉ
  2011.  
  2012. Carsten Whimster 
  2013.  
  2014. Carsten is an undergraduate Computer Science student at the University of 
  2015. Waterloo.  He is currently in fourth year, and enjoying it immensely.  He uses 
  2016. Visual Age C++, Watcom C/C++ 10.0a and Watcom VX-REXX 2.0c.  Carsten is the 
  2017. author of some commandline utilities, and POV-Panel/2.  He is also a TEAM-OS/2 
  2018. member, and has adopted a little computer store called The Data Store in 
  2019. Waterloo, Ontario. 
  2020.  
  2021. You may reach Carsten... 
  2022.  
  2023. ...via email (Internet): 
  2024.  
  2025. carsten_whimster@iqpac.com 
  2026.  
  2027. ...via the World Wide Web: 
  2028.  
  2029. http://www.undergrad.math.uwaterloo.ca/~bcrwhims/ 
  2030.  
  2031. ...via snail mail: 
  2032.  
  2033. (I am just about to move.  Hang in there for a month) 
  2034.  
  2035. ...via voice: 
  2036.  
  2037. (519)886-2439 
  2038.  
  2039. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  2040.  
  2041.  
  2042. ΓòÉΓòÉΓòÉ 9.5. Joe Wyatt ΓòÉΓòÉΓòÉ
  2043.  
  2044. Joe Wyatt 
  2045.  
  2046. Joe has been working in OS/2 since 1.3 and has programmed in Rexx on four 
  2047. different platforms.  Rexx projects have included elegant, complex systems in 
  2048. both VM and OS/2, operating system automation in MVS, and your basic "quick and 
  2049. dirty" tools in DOS.  He has recently mustered up the courage to jump into the 
  2050. world of consulting and self-employment.  (God help him.)  He makes his home in 
  2051. San Antonio, Texas with a wife and four children (along with 2 dogs, 1 cat, 1 
  2052. turtle, varying numbers of fish, and a rabbit). 
  2053.  
  2054. He can be reached via internet address jwyatt@txdirect.net for comments and 
  2055. criticisms. 
  2056.  
  2057. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  2058.  
  2059.  
  2060. ΓòÉΓòÉΓòÉ 9.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  2061.  
  2062. Gordon Zeglinski 
  2063.  
  2064. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  2065. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  2066. He has been programming in C++ for 6 years and also has a strong background in 
  2067. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  2068.  
  2069. His current projects include a client/server communications program that 
  2070. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  2071. involved in the development of a "real-time" automated vehicle based on OS/2 
  2072. and using C++ in which he does device driver development and designs the 
  2073. applications that comprise the control logic and user interface. 
  2074.  
  2075. He can be reached via the Internet at gordon_zeglinski@iqpac.com. 
  2076.  
  2077. Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1 
  2078.  
  2079.  
  2080. ΓòÉΓòÉΓòÉ 9.7. Network distributors ΓòÉΓòÉΓòÉ
  2081.  
  2082. Network Distributors 
  2083.  
  2084. These people are part of our distribution system to provide EDM/2 on networks 
  2085. other than the Internet.  Their help to provide access to this magazine for 
  2086. others is voluntary and we appreciate them a lot! 
  2087.  
  2088.      Paul Hethmon (phethmon@utk.edu) - Compuserve 
  2089.      Gess Shankar (gess@knex.mind.org) - Internet 
  2090.      Jason B. Tiller (PeerGynt@aol.com) - America On-line 
  2091.      Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's 
  2092.  
  2093.  If you would like to become a "network distributor", be sure to contact the 
  2094.  editors so that we can give you the credit you deserve! 
  2095.  
  2096.  Contributors - EDM/2 - Jan 1996 - Volume 4, Issue 1