home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 32 Periodic / 32-Periodic.zip / edmi2-10.zip / EDMI2-10.INF (.txt) < prev    next >
OS/2 Help File  |  1994-11-08  |  145KB  |  1,760 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Nov 1994 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                                       EDM/2
  5.  
  6.                   The Electronic Developer's Magazine for OS/2
  7.  
  8.                    Portions copyright (c) by Larry Salomon Jr.
  9.                                Volume 2, issue 10
  10.  
  11. Copyright Notice and Other Stuff 
  12.  
  13. The Editor-in-Chief of this electronic magazine is Larry Salomon, Jr. 
  14.  
  15. Portions of EDM/2 are copyrighted by the editors.  This publication may be 
  16. freely distributed in electronic form provided that all parts are present in 
  17. their original unmodified form.  A reasonable fee may be charged for the 
  18. physical act of distribution; no fee may be charged for the publication itself. 
  19.  
  20. All articles are copyrighted by their authors. No part of any article may be 
  21. reproduced without permission from the original author. 
  22.  
  23. Neither this publication nor the editors are affiliated with International 
  24. Business Machines Corporation. 
  25.  
  26. OS/2 is a registered trademark of International Business Machines Corporation. 
  27. Other trademarks are property of their respective owners.  Any mention of a 
  28. product in this publication does not constitute an endorsement or affiliation 
  29. unless specifically stated in the text. 
  30.  
  31. Administrivia 
  32.  
  33. What a month it has been!  By the time you read this, OS/2 3.0 Warp will be 
  34. available in (hopefully) stores everywhere and you may be reading this issue 
  35. using Warp on your computer.  I had the pleasure of finding a shrink-wrapped 
  36. copy sent by IBM on my doorstep in mid-October, which I installed the next day. 
  37. After almost a month of use, I must say that IBM has a winner here... 
  38.  
  39. If they can market it effectively, that is.  IBM is as notorious for poor 
  40. marketing as Microsoft is for missing deadlines.  Will they be able to change? 
  41. Who can say?  IBM has two things going for them, however:  a new advertising 
  42. agency and a new budget.  The possibilities are there; now it is up to IBM to 
  43. realize this new-found potential. 
  44.  
  45. Support Your Favorite Operating System 
  46.  
  47. Fortunately, we can aid IBM in its struggle against the behemoth. Team-OS/2 is 
  48. an excellent organization that coordinates the world-wide battle to evangelize 
  49. OS/2 and its advantages versus Windows.  A number of well-known IBMers are 
  50. affiliated, though not officially, with this organization.  Check with your 
  51. local IBM office to see how you can be put in touch in order to help out in 
  52. your neck-of-the-woods. 
  53.  
  54. Like I Said... 
  55.  
  56. "By the time you read this..."  During the development of the sample for the 
  57. Introduction to PM Programming column, all-of-a-sudden the Resource Compiler 
  58. stopped working.  After two days of unsuccessfully beating on my machine, I 
  59. thought that maybe it was an environment inconsistency that occurred when I 
  60. installed Warp and forgot to save my CONFIG.SYS (and thus had to rebuild the 
  61. development-related sections manually).  So, I uninstalled the Toolkit and 
  62. C-Set++ and reinstalled them. 
  63.  
  64. Nothing different.  RC still hung apparently somewhere in the middle of 
  65. including <os2.h>. 
  66.  
  67. After two more reinstalls of both products, I decided - on a whim - to try 
  68. running RC against another source file and, to my chagrin, it worked.  "It must 
  69. be," I thought, "a problem with the BUTTON.RC file."  So I pulled up my editor 
  70. to find a hex x'02' character at the end of one of the lines.  Ironically, this 
  71. is a smiley face; I suppose someone was laughing during both days while I was 
  72. going nuts trying to get this to work (so that I could finish the magazine). 
  73.  
  74. Now, my qualm with the whole situation is with the (lack of) error recovery in 
  75. RC.  This has happened to me once before but (obviously) I didn't bother 
  76. jotting down what the cause of the error was.  I claim, though, that I 
  77. shouldn't have to if RC would simply report errors when it sees them. Remember 
  78. this one? 
  79.  
  80. BUTTON.RES(0):  I/O error.  Attempting to continue...
  81.  
  82. For those of you who haven't seen this error before, it happens most frequently 
  83. when the RES file was not generated because the user pressed Ctrl-Break in the 
  84. middle of the compilation.  Has anyone in the Toolkit Department in Boca Raton 
  85. ever heard of the remove() function?  No, I suppose not, or this message would 
  86. have been removed a long time ago when IBM received the code from Microsoft for 
  87. the Toolkit utilities. 
  88.  
  89. Looking to Steal a Good Idea 
  90.  
  91. In the "Quest of the Month" department, I am trying to steal; yes, I want to 
  92. steal a good idea from another great electronic magazine, OS/2 Personal.  In 
  93. order to make it easier for people to write, I want to change our source format 
  94. from OS/2's Information Presentation Facility (IPF) format to Rich Text Format 
  95. (RTF).  This would allow future authors to write their articles in any one of 
  96. the many word processors that support this format on export. 
  97.  
  98. The problem which I am trying to solve is in the translation from RTF to INF 
  99. for viewing by our many readers.  If you have a solution to this interesting 
  100. problem (perhaps an RTF to IPF compiler?), please contact me via email; I'd 
  101. love to hear what information you can provide. 
  102.  
  103. Washing Up Gets Rids of Dirt 
  104.  
  105. I was conversing with someone through email and he mentioned something called 
  106. Clean, so the obvious question in my mind was, "What is it?"  It is apparently 
  107. a functional programming language, which means that all programs written in the 
  108. language are comprised solely of functions.  To use the example given to me, 
  109. consider the function to calculate the factorial of a number: 
  110.  
  111. Fac:: Int -> Int
  112. Fac 1 = 1;
  113. Fac n = n * Fac (n - 1);
  114.  
  115. That should be enough to whet your attetite.  Clean is available for the OS/2, 
  116. Mac, Sun, and Linux platforms and the latest version (0.8) can be obtained via 
  117. anonymous FTP from ftp.cs.kun.nl. 
  118.  
  119. Washing Up Gets Rid of Bugs 
  120.  
  121. And while the latest CSD from IBM would also appear to do this, according to 
  122. David Charlap, it could have done a better job.  "Fixpacks" XR_A056 and XR_A058 
  123. are available for OS/2 2.11 which fix, among other things, some interesting Gpi 
  124. bugs.  However, David mentioned that, after installing both of these CSD's, 
  125. IPMD started behaving weirdly and that a bug report was sent to the C-Set++ 
  126. group.  We will keep you posted as he sends us new information. Thanks, David, 
  127. for your note. 
  128.  
  129. Reader's Choice Awards 
  130.  
  131. This is your friendly reminder that, next month, we will conduct our Reader's 
  132. Choice Awards for the year 1994.  I sincerely hope to receive more than 14 
  133. votes for the best articles of the year.  <grin> 
  134.  
  135. Title Page - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  136.  
  137.  
  138. ΓòÉΓòÉΓòÉ 2. The Design and Implementation of VIOWIN - Part 3 ΓòÉΓòÉΓòÉ
  139.  
  140.  
  141. ΓòÉΓòÉΓòÉ 2.1. Introduction ΓòÉΓòÉΓòÉ
  142.  
  143. The Design and Implementation of VIOWIN - Part 3 
  144.  
  145. Written by Larry Salomon, Jr. 
  146.  
  147. Introduction 
  148.  
  149. For my job, I once had to write an application that ran only when OS/2 booted 
  150. from the floppy diskettes.  Because I had no access to the functionality PM 
  151. provides, I resorted to a line-oriented interface, where messages were 
  152. displayed on the screen and scrolled up when necessary.  It was a good 
  153. interface, I thought; it was fully NLS enabled and had intelligent defaults so 
  154. the user basically only had to type in the name of the application. 
  155. Unfortunately, the Quality Assurance team didn't concur with my opinion.  "We 
  156. want a nice interface!" one exclaimed.  "Yeah, one with different windows and 
  157. such!" another shouted. 
  158.  
  159. I was backed into a corner that I could only get out of one way. 
  160.  
  161. This series describes the design and implementation of VIOWIN, a library that 
  162. implements a subset of the Win APIs provided by PM for fullscreen sessions. 
  163. The reasoning behind writing this series is that it provided me and will 
  164. hopefully provide you with some unique insights into how a windowing system is 
  165. developed; and since it is based on PM, your familiarity with the already 
  166. defined interface will increase your capability to fully understand what is 
  167. being described. 
  168.  
  169. Obviously, this series assumes you have PM application development experience, 
  170. but it isn't required. 
  171.  
  172. Last Month 
  173.  
  174. Last month, we looked at the design of the keyboard monitor which provides the 
  175. WM_CHAR messages to the system and how the design lent itself to a more 
  176. difficult implementation.  This month, we will continue by looking at the 
  177. remaining functions that are called from within the main() function. 
  178.  
  179. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  180. Issue 10 
  181.  
  182.  
  183. ΓòÉΓòÉΓòÉ 2.2. Errata ΓòÉΓòÉΓòÉ
  184.  
  185. Errata 
  186.  
  187. Before we do anything, however, a correction needs to be made.  In postKeyMsg() 
  188. there was the following code: 
  189.  
  190. case 0x37:
  191.    usFlags|=KC_VIRTUALKEY;
  192.    usVkey=VK_PRINTSCRN;
  193.    break;
  194.  
  195. This code was written with the intent of allowing me to press the PrintScrn key 
  196. and get a screen dump in a held printer queue using the IBMNULL printer driver. 
  197. After you finish laughing at the stupidity of my assumption that this will do 
  198. the trick, you will realize that 0x37 is the scan code of the "7" key and that 
  199. it will not work if this code is left in.  Thus, it was removed. 
  200.  
  201. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  202. Issue 10 
  203.  
  204.  
  205. ΓòÉΓòÉΓòÉ 2.3. Classes ΓòÉΓòÉΓòÉ
  206.  
  207. Classes 
  208.  
  209. Since the first thing a PM application typically does after initialization is 
  210. register a private window class or two, let's look at this code first. 
  211.  
  212. SHORT EXPENTRY _findClass(PVWCLASSINFO pciInfo,PCHAR pchClass)
  213. //-------------------------------------------------------------------------
  214. // This function compares the name of the specified class to see if it
  215. // matches the specified name.  It is called by CmnLstSearchRecord().
  216. //
  217. // Input:  pciInfo - points to a VWCLASSINFO structure
  218. //         pchClass - points to the class name to compare with
  219. // Returns:  0 if match, non-0 otherwise
  220. //-------------------------------------------------------------------------
  221. {
  222.    return (strcmp(pciInfo->achName,pchClass)!=0);
  223. }
  224.  
  225. BOOL EXPENTRY vwRegisterClass(PCHAR pchClass,PFNVWWP pfnWndProc)
  226. //-------------------------------------------------------------------------
  227. // This function registers the class with the name specified.
  228. //
  229. // Input:  pchClass - points to the name of the class
  230. //         pfnWndProc - points to the window procedure for the class
  231. // Returns:  TRUE if successful, FALSE otherwise
  232. //-------------------------------------------------------------------------
  233. {
  234.    VWCLASSINFO ciInfo;
  235.  
  236.    if (hmqQueue==NULL) {
  237.       return FALSE;
  238.    } /* endif */
  239.  
  240.    if (CmnLstSearchRecord(CmnLstQueryRecord(habAnchor->hclClasses,0),
  241.                           pchClass,
  242.                           (PFNRECCOMP)_findClass)!=NULL) {
  243.       return FALSE;
  244.    } /* endif */
  245.  
  246.    strcpy(ciInfo.achName,pchClass);
  247.    ciInfo.pfnWndProc=pfnWndProc;
  248.  
  249.    return CmnLstAddRecord(habAnchor->hclClasses,&ciInfo,LAR_TAIL,NULL);
  250. }
  251.  
  252. This function is fairly trivial - it checks to see if vwInitialize() has been 
  253. called by checking the value of hmqQueue.  It then searches the class list to 
  254. see if the class name is already used.  See the documentation for the Common/2 
  255. library for more information about the linked-list routines.  If the class was 
  256. not found, it is added to the class list via CmnLstAddRecord(). 
  257.  
  258. Note! 
  259.  
  260. You should note the deviations from PM:  there are no class styles and there is 
  261. no way to get more than the 8 bytes of window words as provided by the VWWND 
  262. structure (see volume 2, issue 8). 
  263.  
  264. There are two other trivial functions dealing with classes - vwQueryClassName() 
  265. and vwQueryClassInfo() - which we will not discuss here, but are included in 
  266. the sample source provided with this article. 
  267.  
  268. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  269. Issue 10 
  270.  
  271.  
  272. ΓòÉΓòÉΓòÉ 2.4. Windows ΓòÉΓòÉΓòÉ
  273.  
  274. Windows 
  275.  
  276. The next thing that is done is to create a window, so let's look at 
  277. vwCreateWindow() and vwDestroyWindow(). 
  278.  
  279. HVWWND EXPENTRY vwCreateWindow(PCHAR pchClass,
  280.                                USHORT usId,
  281.                                ULONG ulStyle,
  282.                                PCHAR pchText,
  283.                                LONG lX,
  284.                                LONG lY,
  285.                                ULONG ulCx,
  286.                                ULONG ulCy,
  287.                                LONG lForeClr,
  288.                                LONG lBackClr)
  289. //-------------------------------------------------------------------------
  290. // This function creates a window.
  291. //
  292. // Input:  pchClass - points to the name of the class of the window
  293. //         usId - specifies the window id.  If -1 is specified, the check
  294. //                for other windows with the same id is not performed.
  295. //         ulStyle - specifies the style of the window
  296. //         pchText - points to the text of the window
  297. //         lX, lY - specifies the lower left corner of the window, relative
  298. //                  to the desktop
  299. //         ulCx, ulCy - specifies the width and height of the window
  300. //         lForeClr - specifies the VWCLR_* constant for the foreground color
  301. //         lBackClr - specifies the VWCLR_* constant for the background color
  302. // Returns:  window handle if successful, NULLHANDLE otherwise
  303. //-------------------------------------------------------------------------
  304. {
  305.    PVWCLASSINFO pciClass;
  306.    VWWND vwWnd;
  307.    HVWWND hwndNew;
  308.    BOOL bDesktop;
  309.  
  310.    if (hmqQueue==NULL) {
  311.       return NULL;
  312.    } /* endif */
  313.  
  314.    //----------------------------------------------------------------------
  315.    // Make sure the class was registered
  316.    //----------------------------------------------------------------------
  317.    pciClass=(PVWCLASSINFO)CmnLstQueryRecord(habAnchor->hclClasses,0);
  318.    pciClass=(PVWCLASSINFO)CmnLstSearchRecord(pciClass,
  319.                                              pchClass,
  320.                                              (PFNRECCOMP)_findClass);
  321.    if (pciClass==NULL) {
  322.       return NULL;
  323.    } /* endif */
  324.  
  325.    memset(&vwWnd,0,sizeof(VWWND));
  326.    vwWnd.ulSzStruct=sizeof(VWWND);
  327.    vwWnd.pciClass=pciClass;
  328.  
  329.    //----------------------------------------------------------------------
  330.    // If the window id is not -1, check for another window with this id.
  331.    //----------------------------------------------------------------------
  332.    if ((usId!=-1) && (vwWindowFromID(usId)!=NULL)) {
  333.       return NULL;
  334.    } /* endif */
  335.  
  336.    //----------------------------------------------------------------------
  337.    // If there are no other windows, then this window's id *must* be
  338.    // VWWID_DESKTOP.
  339.    //----------------------------------------------------------------------
  340.    if ((CmnLstQueryRecordCount(habAnchor->hclWindows)==0) &&
  341.        (usId!=VWWID_DESKTOP)) {
  342.       return NULL;
  343.    } /* endif */
  344.  
  345.    vwWnd.usId=usId;
  346.    vwWnd.ulStyle=ulStyle;
  347.    vwWnd.swpSwp.lX=lX;
  348.    vwWnd.swpSwp.lY=lY;
  349.    vwWnd.swpSwp.ulCx=ulCx;
  350.    vwWnd.swpSwp.ulCy=ulCy;
  351.    vwWnd.lForeClr=lForeClr;
  352.    vwWnd.lBackClr=lBackClr;
  353.  
  354.    if (!CmnLstAddRecord(habAnchor->hclWindows,
  355.                         &vwWnd,
  356.                         LAR_TAIL,
  357.                         (PPVOID)&hwndNew)) {
  358.       return NULL;
  359.    } /* endif */
  360.  
  361.    //----------------------------------------------------------------------
  362.    // If this is the desktop, set a flag so that we post it a WM_PAINT
  363.    // instead of sending it the message.
  364.    //----------------------------------------------------------------------
  365.    bDesktop=(usId==VWWID_DESKTOP);
  366.  
  367.    if (bDesktop) {
  368.       habAnchor->ulStatus|=VW_HABST_CREATINGDESK;
  369.    } /* endif */
  370.  
  371.    //----------------------------------------------------------------------
  372.    // Check for valid initialization
  373.    //----------------------------------------------------------------------
  374.    if (LONGFROMMR(vwSendMsg(hwndNew,WM_CREATE,0,0))==TRUE) {
  375.       CmnLstDeleteRecord(habAnchor->hclWindows,hwndNew);
  376.       habAnchor->ulStatus&=~VW_HABST_CREATINGDESK;
  377.       return NULL;
  378.    } /* endif */
  379.  
  380.    if (bDesktop) {
  381.       habAnchor->ulStatus&=~VW_HABST_CREATINGDESK;
  382.    } /* endif */
  383.  
  384.    vwWnd.pchText=NULL;
  385.    vwSetWindowText(hwndNew,pchText);
  386.  
  387.    //----------------------------------------------------------------------
  388.    // Paint
  389.    //----------------------------------------------------------------------
  390.    if ((habAnchor->ulStatus & VW_HABST_CREATINGDESK)==0) {
  391.       vwSendMsg(hwndNew,WM_PAINT,0,0);
  392.    } else {
  393.       vwPostMsg(hwndNew,WM_PAINT,0,0);
  394.    } /* endif */
  395.  
  396.    return hwndNew;
  397. }
  398.  
  399. BOOL EXPENTRY vwDestroyWindow(HVWWND hwndWnd)
  400. //-------------------------------------------------------------------------
  401. // This function destroys a window
  402. //
  403. // Input:  hwndWnd - handle to the window
  404. // Returns:  TRUE if successful, FALSE otherwise
  405. //-------------------------------------------------------------------------
  406. {
  407.    if (hwndWnd==VWHWND_DESKTOP) {
  408.       hwndWnd=vwWindowFromID(VWWID_DESKTOP);
  409.    } /* endif */
  410.  
  411.    if (!vwIsWindow(hwndWnd)) {
  412.       return FALSE;
  413.    } /* endif */
  414.  
  415.    //----------------------------------------------------------------------
  416.    // If this is the desktop window, traverse the window list and destroy
  417.    // all of the children first.
  418.    //----------------------------------------------------------------------
  419.    if (vwQueryWindowUShort(hwndWnd,QWS_ID)==VWWID_DESKTOP) {
  420.       CmnLstTraverseList(habAnchor->hclWindows,(PFNRECFUNC)destroyWindow);
  421.       destroyWindow(hwndWnd);
  422.    } else {
  423.       destroyWindow(hwndWnd);
  424.    } /* endif */
  425.  
  426.    return TRUE;
  427. }
  428.  
  429. Note! 
  430.  
  431. Note the deviations again from PM.  In PM, the desktop is created when the 
  432. system initializes itself.  Since VIOWIN doesn't support parent-child 
  433. relationships unless the parent is the desktop, I decided to let the 
  434. application create the desktop of a class it chooses.  The desktop is 
  435. identified by a special id - VWWID_DESKTOP. 
  436.  
  437. Note! 
  438.  
  439. Since the desktop will usually create a number of child windows, the WM_PAINT 
  440. message is posted and not sent to any children it creates, but is sent to 
  441. itself, through the use of the VW_HABST_CREATINGDESK flag in 
  442. habAnchor->ulStatus.  The intent is to prevent the desktop from painting over 
  443. its children because, if the message were posted, the desktop would receive it 
  444. last. 
  445.  
  446. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  447. Issue 10 
  448.  
  449.  
  450. ΓòÉΓòÉΓòÉ 2.5. Messages ΓòÉΓòÉΓòÉ
  451.  
  452. Messages 
  453.  
  454. The final thing that is done, inside the main() function at least, is to enter 
  455. the message loop. 
  456.  
  457. BOOL EXPENTRY vwGetMsg(PVWQMSG pqmMsg)
  458. //-------------------------------------------------------------------------
  459. // This function gets the next message from the circular queue.
  460. //
  461. // Input:  pqmMsg - points to the VWQMSG structure
  462. // Output:  pqmMsg - points to the initialized VWQMSG structure
  463. // Returns:  TRUE if successful, FALSE otherwise
  464. //-------------------------------------------------------------------------
  465. {
  466.    if (hmqQueue==NULL) {
  467.       return FALSE;
  468.    } /* endif */
  469.  
  470.    while (hmqQueue->ulTail==hmqQueue->ulHead) {
  471.       DosSleep(0);
  472.    } /* endwhile */
  473.  
  474.    hmqQueue->ulHead++;
  475.    if (hmqQueue->ulHead==VW_SIZEQUEUE) {
  476.       hmqQueue->ulHead=0;
  477.    } /* endif */
  478.  
  479.    *pqmMsg=hmqQueue->aqmMsgs[hmqQueue->ulHead];
  480.    return (pqmMsg->ulMsg!=WM_QUIT);
  481. }
  482.  
  483. BOOL EXPENTRY vwDispatchMsg(PVWQMSG pqmMsg)
  484. //-------------------------------------------------------------------------
  485. // This function calls the appropriate window procedure with the appropriate
  486. // parameters.
  487. //
  488. // Input:  pqmMsg - points to the initialized VWQMSG structure
  489. // Returns:  TRUE if successful, FALSE otherwise
  490. //-------------------------------------------------------------------------
  491. {
  492.    if (hmqQueue==NULL) {
  493.       return FALSE;
  494.    } /* endif */
  495.  
  496.    (*pqmMsg->hwndWnd->pciClass->pfnWndProc)(pqmMsg->hwndWnd,
  497.                                             pqmMsg->ulMsg,
  498.                                             pqmMsg->mpParm1,
  499.                                             pqmMsg->mpParm2);
  500.    return TRUE;
  501. }
  502.  
  503. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  504. Issue 10 
  505.  
  506.  
  507. ΓòÉΓòÉΓòÉ 2.6. This Is Too Easy ΓòÉΓòÉΓòÉ
  508.  
  509. This Is Too Easy 
  510.  
  511. By now, you're probably thinking, "Wake me up when we get to something that 
  512. requires more intelligence than that of a second grade child."  You are right; 
  513. everything we've seen is quite easily done.  However, I must stress that the 
  514. linked-list routines, which I said before were used heavily, are not shown here 
  515. and they would take up a good sized portion of the code (but that's why there 
  516. are DLL's, correct?).  Also, these are the base routines, so they should be 
  517. simplistic; the hard stuff comes later with the timers and such. 
  518.  
  519. In other words, be patient but (by the same token) don't expect too much. 
  520.  
  521. You should be aware that we have seen the code for all of the functions that 
  522. are used in a typical main() function in a PM application. Next month, we will 
  523. look at more of the window management functions as well as vwPostMsg() and 
  524. vwSendMsg() and other stuff. 
  525.  
  526. The Design and Implementation of VIOWIN (Part 3) - EDM/2 - Nov 1994 - Volume 2, 
  527. Issue 10 
  528.  
  529.  
  530. ΓòÉΓòÉΓòÉ 3. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
  531.  
  532.  
  533. ΓòÉΓòÉΓòÉ 3.1. Introduction ΓòÉΓòÉΓòÉ
  534.  
  535. /dev/EDM2/BookReview 
  536.  
  537. Written by Carsten Whimster 
  538.  
  539. Introduction 
  540.  
  541. /dev/EDM2/BookReview is a monthly column which focuses on development oriented 
  542. books and materials.  The column is from a beginning PM programmer, but 
  543. intermediate REXX programmer's eyes.  Pick up whichever book strikes your 
  544. fancy, and join the growing group of people following our PM programming 
  545. columns.  I will review books aimed at beginners for a while, and then move on 
  546. from there. 
  547.  
  548. Please send me your comments and thoughts so that I can make this column as 
  549. good as possible.  All mail gets read and responded to. 
  550.  
  551. Application Development Using OS/2 REXX is a fairly fast-paced REXX book.  It 
  552. covers some unusual and rare material in some depth. 
  553.  
  554. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  555.  
  556.  
  557. ΓòÉΓòÉΓòÉ 3.2. Errata ΓòÉΓòÉΓòÉ
  558.  
  559. Errata 
  560.  
  561. Well, my WWW homepage is up and running again.  Hopefully I'll catch up with my 
  562. work at school soon, so that I can start expanding it, complete the index and 
  563. so on.  I still have to get it installed onto our school's system, so it is not 
  564. accesible yet. 
  565.  
  566. I tried to get in touch with Charles Petzold regarding his new book OS/2 
  567. Presentation Manager Programming, but he never responded, so maybe I have the 
  568. wrong address.  In any case, I went out and bought the book.  Look for the 
  569. review next month. 
  570.  
  571. With the imminent release of OS/2 Warp 3.0, I have decided to delay the 
  572. purchase of OS/2 Unleashed, until the new version is released.  I picked up a 
  573. list of all the new books planned specifically for Warp, and I was quite 
  574. surprised.  This list looks larger than the complete list of books for OS/2 2.0 
  575. (well, maybe not quite)!  There are some really decent books on it too, among 
  576. others a new (and much needed) version of OS/2 Presentation Manager GPI, Winn. 
  577. I reviewed the old version recently, and basically thought it was a decent book 
  578. badly in need of updating (it was written for OS/2 1.3!); it should be popular 
  579. too, judging from the number of people who have requested a good GPI book over 
  580. the last few months. 
  581.  
  582. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  583.  
  584.  
  585. ΓòÉΓòÉΓòÉ 3.3. Application Development Using OS/2 REXX ΓòÉΓòÉΓòÉ
  586.  
  587. Application Development Using OS/2 
  588.  
  589. Application Development Using OS/2 REXX starts out on a funny note...let me 
  590. explain.  The following is an excerpt from the introduction: 
  591.  
  592. The title of this book Mastering OS/2 REXX:  The Practical Usage
  593. of OS/2 REXX reveals the purpose I had in writing it:  a
  594. concise, but complete, source of information necessary to master the REXX
  595. language for applications in the OS/2 environment.
  596.  
  597. I spent a few moments verifying that I was indeed reading Application 
  598. Development Using OS/2 REXX, and then I wondered about this error.  I suppose 
  599. that since Mastering OS/2 REXX (Gargiulo) was released by the same publisher, 
  600. the editors probably suggested the name change, but one would think that they 
  601. would have looked through the book and fixed the relevant parts?  That doesn't 
  602. inspire confidence, that's for sure.  In any case, I read on, and what Rudd 
  603. said is not just idle talk. Here are the chapter headings: 
  604.  
  605.  1. Introduction 
  606.  2. REXX Concepts 
  607.  3. REXX Program Elements 
  608.  4. Parsing 
  609.  5. Arithmetic 
  610.  6. Input/Output 
  611.  7. Debugging 
  612.  8. Programming Practices 
  613.  9. REXX Instructions 
  614. 10. REXX Built-In Functions (SAA) 
  615. 11. REXX Built-In Functions (Non-SAA) 
  616. 12. Utility Routines 
  617. 13. Worked Example 
  618. 14. REXXUTIL Utility Functions 
  619. 15. Host Commands 
  620. 16. Application Programming Interface 
  621. 17. Service Routines 
  622. 18. Worked Example (Programmed Implementation) 
  623. 19. Database Manager Interface 
  624. 20. Personal REXX 
  625. 21. Other Products 
  626. 22. Appendix A: REXX Instruction Syntax 
  627. 23. Appendix B: Syntax Notation 
  628. 24. Appendix C: Bibliography 
  629. 25. Appendix D: Glossary 
  630. 26. Appendix E: Compatibility (Various Implementations) 
  631. 27. Appendix F: REXX Data Types 
  632. 28. Appendix G: Useful Control Program Services 
  633. 29. Appendix H: RXSTRING Processing Routines 
  634. 30. Appendix I: Function Migration 
  635. 31. Appendix J: Program Preparation 
  636.  
  637. The first few chapters form the obligatory REXX introduction, and since I have 
  638. done a few of those recently, I'll skip over it lightly.  Basically, you learn 
  639. the answer to the following questions: 
  640.  
  641. o What is REXX? 
  642. o Where did REXX come from? 
  643. o What does REXX do? 
  644. o Where can I use REXX? 
  645. o What is in the future for REXX? 
  646. o What is the OS/2 version of REXX like? 
  647. o What does a REXX program look like? 
  648. o What do REXX statements look like? 
  649. o How do I write REXX statements? 
  650. o What are REXX variables like? 
  651. o How does REXX interpret statements? 
  652. o How do I run a REXX program? 
  653. o What flow control constructs does REXX have? 
  654. o What are REXX queues? 
  655.  
  656. Parsing is explained next, and although the chapter is not long, it is quite 
  657. good.  Arithmetic follows, and REXX's arbitrary precision is demonstrated along 
  658. with numeric formats and sequence of operators. Input/output streams are 
  659. explained, with sections on buffering, files, terminals, characters, and 
  660. various other topics following.  A chapter is devoted to debugging, but since 
  661. this is not a topic which is frequently found in this type of book, I would 
  662. have liked to see a more thorough treatment. Nevertheless, there are no glaring 
  663. omissions, just a few vague points. 
  664.  
  665. Chapter 8 is a rare piece on programming practices.  I would love to see more 
  666. information like this in programming books, but it is unfortunately frequently 
  667. skipped over.  This chapter helps the novice/intermediate programmer to learn 
  668. about good programming habits, and maintenance/performance issues.  The chapter 
  669. is good, but a bit short. 
  670.  
  671. Chapters 9 to 12 combine to make an oddly placed, but well-written reference 
  672. section.  The syntax and parameters of REXX instructions, built-in functions 
  673. (SAA), built-in functions (non-SAA), and utility functions are all presented 
  674. rigorously. 
  675.  
  676. Chapter 13 confirms the unusual direction this book has been given, which we 
  677. had a glimpse of in chapter 8.  The chapter consists of a 49 line program which 
  678. implements the DISKW operation of the EXECIO command found in MVS and VM/CMS 
  679. environments.  The syntax is presented, followed by the program, and finally a 
  680. line-by-line explanation of the program.  This type of real-world program can 
  681. teach REXX far more effectively than a million small programs can. The reader 
  682. gets a chance to see how a REXX programmer solves a real problem. The chapter 
  683. is short, but other writers should take notice.  This is a great idea.  Of 
  684. course, this program is probably too complicated for a novice, but it is 
  685. refreshing to see a program which actually does something useful, rather than 
  686. the "Hello World" variety (which does have its place, however). 
  687.  
  688. After the sample program, the book launches into an "advanced" section. This 
  689. section consists of discussions of such topics as REXXUTIL (REXXUTIL is a DLL 
  690. with OS/2 specific commands) with an example of how to do full-screen 
  691. input/output, and host commands (starting DOS and OS/2 sessions and so on). 
  692.  
  693. Chapter 16 introduces the topic of interfacing with other programming languages 
  694. and programs.  Specifically, it shows how to include REXX functions or programs 
  695. from C code, and gives some decent examples of how to do this.  It even gives a 
  696. brief example of how to call REXX from PL/I.  The inclusion of this chapter, 
  697. which is one of the longer ones in the book, goes a long way towards 
  698. demonstrating the intent of this book.  It may sound like a REXX how-to book 
  699. for beginning and intermediate REXX programmers, but when you look a little 
  700. closer, there is some serious information here for the advanced programmer who 
  701. already knows REXX, and needs a book which covers the unusual, and acts like a 
  702. reference manual as well.  Chapter 17 then adds to this by explaining how to 
  703. register external functions for use within REXX. 
  704.  
  705. Chapter 18 is another "worked example"; this time it expands on the example in 
  706. chapter 13, and the result is FEXECIO, a routine which can process a whole file 
  707. in one call.  The surprise is that it is written in C, and calls REXX routines 
  708. to do the dirty work. 
  709.  
  710. The third part of the book is about "applications".  The emphasis here is on 
  711. how to use REXX for real-world productivity solutions, such as interfacing with 
  712. DB2/2.  As in previous examples, some real SQL calls are demonstrated, and 
  713. decent code snippets are given.  Personal REXX from Quercus Systems, and some 
  714. other REXX products are given a brief treatment, among which is VX-REXX. The 
  715. appendices are all very brief and their titles pretty well explain what they 
  716. are all about, so I'll skip them here. 
  717.  
  718. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  719.  
  720.  
  721. ΓòÉΓòÉΓòÉ 3.4. Summary ΓòÉΓòÉΓòÉ
  722.  
  723. Summary 
  724.  
  725. Application Development Using OS/2 REXX is a unique kind of book.  It has 
  726. enough reference material in it to serve as a decent reference manual, but it 
  727. also has good sections on programming and debugging techniques, and interfacing 
  728. with C and DB2/2.  It covers far more than a book this size has a right to, but 
  729. sacrifices a little depth in places.  As a consequence, beginners should 
  730. probably stay away from this book until they are reasonably fluent with REXX. 
  731. If your needs are unusual, however, and all you need is a pointer in the right 
  732. direction, then this book is for you. 
  733.  
  734. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  735.  
  736.  
  737. ΓòÉΓòÉΓòÉ 3.5. Books Reviewed ΓòÉΓòÉΓòÉ
  738.  
  739. Books Reviewed 
  740.  
  741. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  742. ΓöéBOOK                              ΓöéAUDIENCE    ΓöéMARKΓöéCOMMENTS                               Γöé
  743. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  744. ΓöéReal-World Programming for OS/2   ΓöéIntermediateΓöéB+  ΓöéLots of good code examples, but        Γöé
  745. Γöé2.1, Blain, Delimon, and English, Γöéto Advanced Γöé    Γöésometimes it is too complex for        Γöé
  746. ΓöéSAMS Publishing.  ISBN            ΓöéPM C        Γöé    Γöénovices. Accurate.  Well organized.    Γöé
  747. Γöé0-672-30300-0.  US$40, CAN$50.    Γöéprogrammers Γöé    ΓöéThe index needs a little beefing up.   Γöé
  748. Γöé                                  Γöé            Γöé    ΓöéGood, but not entirely complete how-to Γöé
  749. Γöé                                  Γöé            Γöé    Γöéreference.  Good purchase.             Γöé
  750. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  751. ΓöéLearning to Program OS/2 2.0      ΓöéBeginning PMΓöéB-  ΓöéThis book can be both frustrating and  Γöé
  752. ΓöéPresentation Manager by Example,  ΓöéC           Γöé    Γöévery rewarding.  It is not very large, Γöé
  753. ΓöéKnight, Van Nostrand Reinhold.    ΓöéProgrammers Γöé    Γöéand a bit pricey, but has some         Γöé
  754. ΓöéISBN 0-442-01292-6.  US$40,       Γöé            Γöé    Γöéexcellent chapters on certain beginningΓöé
  755. ΓöéCAN$50.                           Γöé            Γöé    Γöétopics, such as messages, resources,   Γöé
  756. Γöé                                  Γöé            Γöé    ΓöéIPF, and dialog boxes.  Strictly for   Γöé
  757. Γöé                                  Γöé            Γöé    Γöébeginners.  This book has only one     Γöé
  758. Γöé                                  Γöé            Γöé    Γöé(large) sample program!                Γöé
  759. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  760. ΓöéWriting OS/2 2.1 Device Drivers inΓöéAdvanced C  ΓöéA-  ΓöéThe only thing a device driver         Γöé
  761. ΓöéC, 2nd Edition, Mastrianni, Van   ΓöéProgrammers,Γöé    Γöéprogrammer would not find in here is   Γöé
  762. ΓöéNostrand Reinhold.  ISBN          Γöéfamiliar    Γöé    Γöéhow to write SCSI, ADD, and IFS        Γöé
  763. Γöé0-442-01729-4.  US$35, CAN$45.    Γöéwith        Γöé    Γöédrivers.  Most everything else is in   Γöé
  764. Γöé                                  Γöéhardware    Γöé    Γöéhere, along with skeleton examples.  AnΓöé
  765. Γöé                                  Γöéprogramming Γöé    Γöéoptional DevHlp library of C-callable  Γöé
  766. Γöé                                  Γöé            Γöé    Γöéfunctions can be purchased by those whoΓöé
  767. Γöé                                  Γöé            Γöé    Γöédon't have time to write their own.    Γöé
  768. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  769. ΓöéOS/2 Presentation Manager GPI,    ΓöéIntermediateΓöéC+  ΓöéThis book needs updating for OS/2 2.x. Γöé
  770. ΓöéWinn, Van Nostrand Reinhold. ISBN Γöéto advanced Γöé    ΓöéIt is a well-written in-depth coverage Γöé
  771. Γöé0-442-00739-6.  US$35, CAN$45.    ΓöéPM C        Γöé    Γöéof the OS/2 way of programming for     Γöé
  772. Γöé                                  Γöéprogrammers Γöé    Γöégraphics.  It is not an introductory PMΓöé
  773. Γöé                                  Γöé            Γöé    Γöéor graphics programming book.  You     Γöé
  774. Γöé                                  Γöé            Γöé    Γöéshould know the basics of PM           Γöé
  775. Γöé                                  Γöé            Γöé    Γöéprogramming already.                   Γöé
  776. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  777. ΓöéThe Art of OS/2 2.1 C Programming,ΓöéBeginning   ΓöéB+  ΓöéThis is a great introductory PM        Γöé
  778. ΓöéPanov, Salomon, and Panov,        ΓöéOS/2 and PM Γöé    Γöéprogramming book.  It covers basic OS/2Γöé
  779. ΓöéWiley-QED.  ISBN 0-471-58802-4.   Γöéprogrammers Γöé    Γöéissues like threads before it jumps    Γöé
  780. ΓöéUS$40, CAN$50.                    Γöé            Γöé    Γöéinto PM programming.  The coverage is  Γöé
  781. Γöé                                  Γöé            Γöé    Γöéquite thorough, with just enough       Γöé
  782. Γöé                                  Γöé            Γöé    Γöéreference material to make it useful   Γöé
  783. Γöé                                  Γöé            Γöé    Γöéafter you read it through the first    Γöé
  784. Γöé                                  Γöé            Γöé    Γöétime.  The upcoming revised edition    Γöé
  785. Γöé                                  Γöé            Γöé    Γöéshould be a killer.                    Γöé
  786. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  787. ΓöéMastering OS/2 REXX, Gargiulo,    ΓöéIntermediateΓöéB   ΓöéThis book is very easy to understand.  Γöé
  788. ΓöéWiley-QED.  ISBN 0-471-51901-4.   ΓöéOS/2 users  Γöé    ΓöéIf you program with any regularity,    Γöé
  789. ΓöéUS$40, CAN$50.                    Γöéand         Γöé    Γöélook elsewhere, but if you need an     Γöé
  790. Γöé                                  Γöébeginning   Γöé    Γöéeasily read, well-explained beginner's Γöé
  791. Γöé                                  Γöéprogrammers Γöé    Γöébook, look no further.  Some more      Γöé
  792. Γöé                                  Γöé            Γöé    Γöédetailed, and complex real-world       Γöé
  793. Γöé                                  Γöé            Γöé    Γöéexamples might be useful as you learn  Γöé
  794. Γöé                                  Γöé            Γöé    Γöéthe material.  Good coverage of REXX's Γöé
  795. Γöé                                  Γöé            Γöé    Γöécapabilities.                          Γöé
  796. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  797. ΓöéREXX Reference Summary Handbook,  ΓöéBeginning toΓöéA   ΓöéThis little handbook is packed full of Γöé
  798. ΓöéGoran, C F S Nevada.  ISBN        Γöéadvanced    Γöé    Γöéuseful information.  Includes chapters Γöé
  799. Γöé0-9639854-1-8.  US$20, CAN$25     ΓöéREXX        Γöé    Γöéon both built-in and some popular      Γöé
  800. Γöé                                  Γöéprogrammers Γöé    Γöécommercial libraries.  Well-written andΓöé
  801. Γöé                                  Γöé            Γöé    Γöécomprehensively indexed.  A must for   Γöé
  802. Γöé                                  Γöé            Γöé    ΓöéREXX programmers.                      Γöé
  803. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  804. ΓöéApplication Development Using OS/2ΓöéIntermediateΓöéA-  ΓöéExcellent coverage of everything REXX, Γöé
  805. ΓöéREXX, Rudd, Wiley-QED. ISBN       Γöéto advanced Γöé    Γöéwith the occasional sparse section. It Γöé
  806. Γöé0-471-60691-X.  US$40, CAN$50     ΓöéREXX        Γöé    Γöéis a decent reference book, and has    Γöé
  807. Γöé                                  Γöéprogrammers Γöé    Γöéenough unusual material that it will   Γöé
  808. Γöé                                  Γöé            Γöé    Γöéprobably find its way into many REXX   Γöé
  809. Γöé                                  Γöé            Γöé    Γöéprogrammers' libraries.                Γöé
  810. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  811.  
  812. This table contains all books I have reviewed, so that you can find what you 
  813. are looking for at a glance.  I will be careful to rate books fairly.  If I 
  814. feel a need to adjust ratings, I will adjust all of them at the same time, and 
  815. write a note explaining why I felt this necessary.  Please note that books 
  816. aimed at different audiences should only be compared with great care, if at 
  817. all.  I intend to concentrate on the strong points of the books I review, but I 
  818. will point out any weaknesses in a constructive manner. 
  819.  
  820. LEGEND: 
  821.  
  822. BOOK:  The name of the book, author(s), publishing company, ISBN, and 
  823. approximate price. 
  824.  
  825. AUDIENCE:  This is a description of the audience I think the book targets best. 
  826. This is not intended as gospel, just a guideline for people not familiar with 
  827. the book. 
  828.  
  829. MARK:  My opinion of the success of the book's presentation, and how well it 
  830. targets its audience.  Technical content, accuracy, organization, readability, 
  831. and quality of index all weigh heavily here, but the single most important item 
  832. is how well the book covers what it says it covers.  Many books try to cover 
  833. too much, and get a lower mark as a result. 
  834.  
  835. ΓöîΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  836. ΓöéA+ ΓöéGround-breaking, all-around outstanding book                               Γöé
  837. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  838. ΓöéA  ΓöéExcellent book.  This is what I want to see happen a lot                   Γöé
  839. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  840. ΓöéA- ΓöéExcellent book with minor flaws                                            Γöé
  841. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  842. ΓöéB+ ΓöéVery good book with minor flaws or omissions                               Γöé
  843. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  844. ΓöéB  ΓöéGood book with some flaws and omissions                                    Γöé
  845. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  846. ΓöéB- ΓöéGood book, but in need of improvement                                      Γöé
  847. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  848. ΓöéC+ ΓöéMediocre book with some potential, but in need of some updating            Γöé
  849. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  850. ΓöéC  ΓöéMediocre book with some good sections, but badly in need of fixing         Γöé
  851. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  852. ΓöéC- ΓöéMediocre book, little good material, desperately in need of an overhaul    Γöé
  853. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  854. ΓöéD  ΓöéDon't buy this book unless you need it, and nothing else exists            Γöé
  855. Γö£ΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  856. ΓöéF  ΓöéDon't buy this book.  Period                                               Γöé
  857. ΓööΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  858.  
  859. COMMENTS:  This is a very brief summary of the review proper. 
  860.  
  861. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  862.  
  863.  
  864. ΓòÉΓòÉΓòÉ 3.6. Content Index ΓòÉΓòÉΓòÉ
  865.  
  866. Content Index 
  867.  
  868. This Content Index is designed to let you find the book that covers the topics 
  869. you need to learn about.  It will eventually have a lot of categories, with 
  870. each book being rated along each row.  This table will be quite large, and will 
  871. continually grow, so please give me your feedback regarding what categories you 
  872. would like to see, and which you don't.  It may take me a while to fill it, so 
  873. have a little patience. 
  874.  
  875. Note:  Books which cover the same material can look similar in this table, but 
  876. be different in real life.  Be sure that the books you are comparing are aimed 
  877. at the same audiences. 
  878.  
  879. PM BOOKS: 
  880.  
  881. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  882. ΓöéBOOK ΓöéMARK ΓöéPM     ΓöéGPI    ΓöéFonts  ΓöéDevice ΓöéPrint  Γöé
  883. Γöé     Γöé     ΓöéIntro  Γöé       Γöé       ΓöéDriver Γöé       Γöé
  884. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  885. ΓöéRWP  ΓöéB+   Γöé4      Γöé4      Γöé4      Γöé0      Γöé3      Γöé
  886. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  887. ΓöéPME  ΓöéB-   Γöé2      Γöé2      Γöé2      Γöé0      Γöé0      Γöé
  888. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  889. ΓöéODD  ΓöéA    Γöé0      Γöé1      Γöé0      Γöé5      Γöé1      Γöé
  890. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  891. ΓöéGPI  ΓöéC+   Γöé0      Γöé5      Γöé2      Γöé0      Γöé3      Γöé
  892. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  893. ΓöéTAO  ΓöéB+   Γöé4      Γöé1      Γöé2      Γöé0      Γöé2      Γöé
  894. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  895.  
  896. REXX BOOKS: 
  897.  
  898. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  899. ΓöéBOOK ΓöéMARK ΓöéREXX     ΓöéWPS      ΓöéReferenceΓöé
  900. Γöé     Γöé     ΓöéIntro    Γöé         Γöé         Γöé
  901. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  902. ΓöéMOR  ΓöéB    Γöé4        Γöé0        Γöé2        Γöé
  903. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  904. ΓöéRSH  ΓöéA    Γöé1        Γöé2        Γöé5        Γöé
  905. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  906. ΓöéADO  ΓöéA-   Γöé3        Γöé0        Γöé4        Γöé
  907. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  908.  
  909. BOOK LEGEND: 
  910.  
  911. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  912. ΓöéReal-World Programming for OS/2 2.1                                ΓöéRWP  Γöé
  913. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  914. ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example       ΓöéPME  Γöé
  915. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  916. ΓöéWriting OS/2 2.1 Device Drivers in C, 2nd Edition                  ΓöéODD  Γöé
  917. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  918. ΓöéOS/2 Presentation Manager GPI                                      ΓöéGPI  Γöé
  919. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  920. ΓöéThe Art of OS/2 2.1 C Programming                                  ΓöéTAO  Γöé
  921. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  922. ΓöéMastering OS/2 REXX                                                ΓöéMOR  Γöé
  923. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  924. ΓöéREXX Reference Summary Handbook                                    ΓöéRSH  Γöé
  925. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  926. ΓöéApplication Development Using OS/2 REXX                            ΓöéADO  Γöé
  927. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  928.  
  929. RATINGS LEGEND: 
  930.  
  931. ΓöîΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  932. Γöé0ΓöéNo coverage           Γöé
  933. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  934. Γöé1ΓöéVery light coverage   Γöé
  935. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  936. Γöé2ΓöéIntroductory coverage Γöé
  937. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  938. Γöé3ΓöéGood Coverage         Γöé
  939. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  940. Γöé4ΓöéIn-depth coverage     Γöé
  941. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  942. Γöé5ΓöéAuthoritative         Γöé
  943. ΓööΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  944.  
  945. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  946.  
  947.  
  948. ΓòÉΓòÉΓòÉ 3.7. Coming Up ΓòÉΓòÉΓòÉ
  949.  
  950. Coming Up 
  951.  
  952. Next month I will be looking at OS/2 Presentation Manager Programming, Petzold. 
  953. The books I intend to review are (not necessarily in this order): 
  954.  
  955. o OS/2 Presentation Manager Programming, Petzold 
  956. o Designing OS/2 Applications, Reich 
  957. o OS/2 Unleashed, Moskowitz and Kerr 
  958. o The Design of OS/2, 2nd Edititon, Kogan and Deitel 
  959.  
  960. I am considering reviewing the IBM OS/2 Redbooks, since they are readily and 
  961. cheaply available, and look like good reference. 
  962.  
  963. If anyone has a book they want to see reviewed, I will be happy to oblige, as 
  964. long as I can afford it.  Of course, requests can be satisfied quicker when 
  965. accompanied by a book :)  Publishers can send me books at the address on my 
  966. personal page at the end of the magazine, and I will review all OS/2 
  967. development-related and advanced user books I receive. 
  968.  
  969. /dev/EDM2/BookReview - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  970.  
  971.  
  972. ΓòÉΓòÉΓòÉ 4. C++ Corner ΓòÉΓòÉΓòÉ
  973.  
  974.  
  975. ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
  976.  
  977. C++ Corner 
  978.  
  979. Written by Gordon Zeglinski 
  980.  
  981. Introduction 
  982.  
  983. So are we sick of SOM yet?  I hope not!  This issue last will be the last 
  984. column on SOM for a while.  We will look at some benchmarks of SOM vs C++ based 
  985. objects.  Hopefully you are a curious as I am about the overhead built into 
  986. SOM. 
  987.  
  988.  
  989. ΓòÉΓòÉΓòÉ 4.2. On with the Benchmark ΓòÉΓòÉΓòÉ
  990.  
  991. What we will try to do here is write a series of tests to determine the 
  992. overhead involved with calling a member function in SOM.  Because we are 
  993. interested only in the function call overhead, the function will simply 
  994. increment a counter variable.  This counter variable will be stored in the 
  995. object's instance data.  For comparison, a C++ version of the SOM object will 
  996. be used to establish a base mark.  The interface definition of the SOM object 
  997. follows. 
  998.  
  999. interface SOMFoo : SOMObject
  1000. {
  1001.  
  1002.    attribute long Count;          // Stores the Count Data
  1003.  
  1004.    void IncrementCount();        //procedure
  1005.    void OffIncrementCount();     //offset
  1006.    void LookIncrementCount();    //lookup
  1007.  
  1008.  
  1009. #ifdef __SOMIDL__
  1010. implementation
  1011. {
  1012.  
  1013.  
  1014.     releaseorder: _get_Count,_set_Count,IncrementCount,\
  1015.                   OffIncrementCount,LookIncrementCount;
  1016.  
  1017.     IncrementCount:     procedure;
  1018.     LookIncrementCount: namelookup;
  1019.  
  1020.     callstyle=oidl;
  1021.     filestem = sombench;
  1022.     somInit: override;  // initialize instance variables to 0
  1023.     somUninit: override; // just for fun
  1024.  
  1025. };
  1026. #endif /* __SOMIDL__ */
  1027. };
  1028.  
  1029. Three functions are defined to test the various resolution methods. 
  1030. IncrementCount is used to test the "procedure" resolution method. A procedure 
  1031. doesn't use a resolution method per se; a procedure is similar to a non-virtual 
  1032. C++ function because it is called by its address. OffIncrementCount is used to 
  1033. test the offset resolution method. This is the default method used by SOM to 
  1034. resolve a function call.  This method is similar to virtual functions in C++. 
  1035. LookIncrementCount is used to test the name lookup resolution method. 
  1036.  
  1037. A function can be labeled a procedure as follows: 
  1038.  
  1039.     IncrementCount:     procedure;
  1040.  
  1041. Because the default "type" for a function is method, one only has to list 
  1042. functions that are to be procedures. 
  1043.  
  1044. Note:  only methods can be overridden. 
  1045.  
  1046. Similarily, one can specify that a method is to lookup offset resolution by 
  1047. using the following: 
  1048.  
  1049.     LookIncrementCount: namelookup;
  1050.  
  1051. Again, one only lists functions which deviate from the normal resolution 
  1052. method.  The normal method is offset. 
  1053.  
  1054. Note:  there seems to be a bug in the C++ emitters. This bug causes incorrect 
  1055. code to be generated for the lookup resolution method. 
  1056.  
  1057. For the C++ object, we use the following class definition : 
  1058.  
  1059.  
  1060. class CPPfoo{
  1061.    int Count;          // Stores the Count Data
  1062.  
  1063. public:
  1064.    CPPfoo();
  1065.    ~CPPfoo();
  1066.  
  1067.    void IncrementCount();                //similar to SOM procedure
  1068.    void InlineIncrementCount(){Count++;} //no equivalence in SOM procedure
  1069.    virtual void OffIncrementCount();     //similar to SOM offset
  1070.  
  1071.    void SetCount(int C){Count=C;}
  1072.    int GetCount(){return Count;}
  1073.  
  1074. };
  1075.  
  1076. The C++ object duplicates the SOM object wherever possible.  The two major 
  1077. differences between tests on the C++ and SOM objects are that the C++ object 
  1078. can't do "name lookup resolution" and the SOM object can't do inline code. 
  1079.  
  1080. Now that we have seen the objects, we can look at how they will be used. Both 
  1081. the C++ and SOM objects are structured similarly, thus, it follows that both of 
  1082. the tests will be implemented similarly. 
  1083.  
  1084. #define INCL_DOS
  1085. #include <os2.h>
  1086.  
  1087. #include "sombench.xh"
  1088. #include <stdio.h>
  1089.  
  1090. void main(){
  1091.    ULONG StartTime, EndTime;
  1092.    int i;
  1093.  
  1094.    SOMFoo *sfoo=new SOMFoo;
  1095.  
  1096.  
  1097.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&StartTime,4); //Get Start time using the system timer
  1098.    for(i=0;i<1000000;i++)
  1099.       SOMFoo::IncrementCount(sfoo);             //lets call the fnc a million times
  1100.  
  1101.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&EndTime,4);   //Get End time we
  1102.  
  1103.    printf("Time for Procedure calls %i ms count= %i\r\n",EndTime-StartTime,sfoo->_get_Count());
  1104.  
  1105.    sfoo->_set_Count(0);
  1106.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&StartTime,4);
  1107.    for(i=0;i<1000000;i++)
  1108.       sfoo->OffIncrementCount();
  1109.  
  1110.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&EndTime,4);
  1111.  
  1112.    printf("Time for Offset lookup calls %i ms count= %i\r\n",EndTime-StartTime,sfoo->_get_Count());
  1113.  
  1114.    sfoo->_set_Count(0);
  1115.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&StartTime,4);
  1116.    for(i=0;i<1000000;i++)
  1117.       lookup_LookIncrementCount(sfoo);
  1118. //      sfoo->LookIncrementCount();
  1119.  
  1120.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&EndTime,4);
  1121.  
  1122.    printf("Time for Name lookup calls #1 %i ms count= %i\r\n",EndTime-StartTime,sfoo->_get_Count());
  1123.  
  1124.    sfoo->_set_Count(0);
  1125.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&StartTime,4);
  1126.    for(i=0;i<1000000;i++)
  1127.       (somResolveByName(sfoo,"LookIncrementCount") )(sfoo);
  1128.  
  1129.    DosQuerySysInfo(QSV_MS_COUNT,QSV_MS_COUNT,&EndTime,4);
  1130.  
  1131.    printf("Time for Name lookup calls #2 %i ms count= %i\r\n",EndTime-StartTime,sfoo->_get_Count());
  1132.  
  1133. }
  1134.  
  1135. To determine the overhead in making the function call, we call the function 1 
  1136. million times.  The time it takes to call the function 1 million times along 
  1137. with the value of the incremented variable is displayed after each iteration. 
  1138. The results of the SOM test follow. 
  1139.  
  1140. Time for Procedure calls 656 ms count= 1000000
  1141. Time for Offset lookup calls 719 ms count= 1000000
  1142. Time for Name lookup calls #1 22031 ms count= 1000000
  1143. Time for Name lookup calls #2 175031 ms count= 1000000
  1144.  
  1145. On a side note, The procedure IncrementCount is emitted as a static member 
  1146. function in C++.  This is strange because you still have to pass it a pointer 
  1147. to the instance of the C++ object that wraps instance SOM object. This of 
  1148. course is exactly what a C++ member function does (in an implicit manner). 
  1149.  
  1150. Running the tests on the C++ object yields the following. 
  1151.  
  1152. Time for Procedure calls 219 ms count= 1000000
  1153. Time for Offset lookup calls 281 ms count= 1000000
  1154. Time for inline calls 0 ms count= 1000000
  1155.  
  1156. Examining the Results 
  1157.  
  1158. As usual to give a benchmark meaning, the system it is run on has to be listed. 
  1159. The following list shows the syslevels of the various components involved in 
  1160. the tests. 
  1161.  
  1162.                       IBM OS/2 Base Operating System
  1163. Version 2.11     Component ID 562107701
  1164. Type 0
  1165. Current CSD level: XR06200
  1166. Prior   CSD level: XR02110
  1167.  
  1168.                       IBM C/C++ Tools (compiler)
  1169. Version 2.00     Component ID 562201703
  1170. Current CSD level: CT00010
  1171. Prior   CSD level: CT00009
  1172.  
  1173.                    SOMobjects Developer Toolkit
  1174. Version 2.00     Component ID 96F8647TK
  1175. Current CSD level: SM20004
  1176. Prior   CSD level: SM00000
  1177.  
  1178. All of this was running on a 486 DX2-66 PC clone machine with 20 megs of RAM. 
  1179.  
  1180. Let's start by looking at the C++ test.  For 1 million calls to a member 
  1181. function, only 219 milliseconds was used.  Calling a virtual function took just 
  1182. slightly more time.  The inline case took no measurable amount of time. What 
  1183. happened most probably in the inline case is that the optimizer completely 
  1184. removed the loop and did a direct assignment instead.  (I haven't checked the 
  1185. compiled code to verify if this is the case or not.  If you are curious feel 
  1186. free to check it yourself.) 
  1187.  
  1188. One of the arguments you see tossed around when arguing the merits of C++ 
  1189. versus C is that the additional amount of time it takes to call a virtual 
  1190. function compared to a normal "C function" is negligible.  This test confirms 
  1191. those arguements.  The overall amount of time used to call one a virtual 
  1192. function for "real cases" is even less important. 
  1193.  
  1194. The offset resolution case in the SOM test took about 2.5 times longer to 
  1195. execute than did the virtual C++ function test.  Recall that the offset 
  1196. resolution case in SOM is equivalent to the virtual function case in C++. There 
  1197. are several ways to call a function by it's name.  In the first name lookup 
  1198. test, we use the macro created by the SOM compiler called 
  1199. lookup_LookIncrementCount.  For the second test, we use somResolveByName.  Note 
  1200. that the difference in execution time between the two lookup tests. 
  1201.  
  1202. Even though the second name lookup case took much longer than the other cases, 
  1203. one should remember that this test does not necessarily represent a real world 
  1204. use of the somResolveByName function.  This function was called a million 
  1205. times.  If one were to write this in an efficient manner, only 1 call would be 
  1206. made to determine the address of the function.  Once this address has been 
  1207. determined, it can be reused inside the loop.  The time used by the revamped 
  1208. lookup test should then approach that of the procedure test. 
  1209.  
  1210. One of the reasons the SOM version is slower than the C++ version is because, 
  1211. in SOM, the object's interface doesn't have to be fully disclosed. The base 
  1212. pointer to the data is not the same as the pointer to the objects instance. 
  1213. Thus, in SOM, one has to query the pointer for the instance data in order to 
  1214. access it.  Consider the following SOM function: 
  1215.  
  1216. SOM_Scope void  SOMLINK OffIncrementCount(SOMFoo *somSelf)
  1217. {
  1218.     SOMFooData *somThis = SOMFooGetData(somSelf);
  1219. //    SOMFooMethodDebug("SOMFoo","OffIncrementCount");
  1220.  
  1221.    (somThis->Count)++;
  1222. }
  1223.  
  1224. Note:  I commented out the debug call to increase performance. 
  1225.  
  1226. Now compare the SOM function to the following C++ member function: 
  1227.  
  1228. void CPPfoo::IncrementCount(){
  1229.    Count++;
  1230. }
  1231.  
  1232. Notice that in the SOM function, we have to determine the value of somThis. 
  1233.  
  1234. Finally a word of caution.  OS/2's time slicing is far too coarse for high 
  1235. degrees of accuracy with numbers this small.  A variation of 32ms (or so) may 
  1236. occur when running these tests, since that is the resolution of the clock used 
  1237. to preempt tasks running within the system. 
  1238.  
  1239. Included Files 
  1240.  
  1241. CPPTEST.CPP         C++ test 
  1242. SOMBENCH.IDL        SOM idl file 
  1243. SOMBENCH.CPP        C++ implementation for SOM object 
  1244. SOMBENCH.XH         SOM header 
  1245. SOMBENCH.XIH        SOM implementation header 
  1246. SOMBTEST.CPP        main routine for SOM tests 
  1247.  
  1248.  
  1249. ΓòÉΓòÉΓòÉ 4.3. Wrapping Things Up ΓòÉΓòÉΓòÉ
  1250.  
  1251. That's it for another fun-filled look at SOM.  It should be noted that there 
  1252. probably will not be an installment of this column next month while I wrap up 
  1253. the development of INTERcomm, a commercial communications package that I have 
  1254. developed. 
  1255.  
  1256.  
  1257. ΓòÉΓòÉΓòÉ 5. Introduction to PM Programming ΓòÉΓòÉΓòÉ
  1258.  
  1259.  
  1260. ΓòÉΓòÉΓòÉ 5.1. Introduction ΓòÉΓòÉΓòÉ
  1261.  
  1262. Introduction to PM Programming 
  1263.  
  1264. Written by Larry Salomon, Jr. 
  1265.  
  1266. Introduction 
  1267.  
  1268. The purpose of this column is to provide the readers out there who are not 
  1269. familiar with PM application development the information necessary to satisfy 
  1270. their curiousity, educate themselves, and give them an advantage over the 
  1271. documentation supplied by IBM.  Of course, much of this stuff could probably be 
  1272. found in one of the many books out there, but the problem with books in general 
  1273. is that they don't answer the questions you have after you read the book the 
  1274. first time through. 
  1275.  
  1276. I will gladly entertain feedback from the readers about what was "glossed over" 
  1277. or what was detailed well, what tangential topics need to be covered and what 
  1278. superfluous crap should have been removed.  This feedback is essential in 
  1279. guaranteeing that you get what you pay for.  :) 
  1280.  
  1281. It should be said that you must not depend solely on this column to teach you 
  1282. how to develop PM applications; instead, this should be viewed as a supplement 
  1283. to your other information storehouses (books, the network conferences, etc.). 
  1284. Because this column must take a general approach, there will be some topics 
  1285. that you would like to see discussed that really do not belong here.  Specific 
  1286. questions can be directed to the Scratch Patch, where an attempt to answer them 
  1287. will be made. 
  1288.  
  1289. Last Month 
  1290.  
  1291. Last month, we looked at the WC_BUTTON class and the five different 
  1292. "subclasses" contained therein.  This month, we will look at a new application 
  1293. - BUTTON - which creates types of all of these controls.  We will also look at 
  1294. the ownerdraw concept and how is specifically applies to button controls. 
  1295.  
  1296. Introduction to PM Programming - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1297.  
  1298.  
  1299. ΓòÉΓòÉΓòÉ 5.2. Good Guys Come Last ΓòÉΓòÉΓòÉ
  1300.  
  1301. Good Guys Come Last 
  1302.  
  1303. And easier concepts come first.  Before we delve into the application, we 
  1304. should understand what ownerdraw controls are.  The idea behind the ownerdraw 
  1305. control is that the application garners the responsibility for painting the 
  1306. control.  This is useful in many situations; you might want to change the 
  1307. appearance of the control (as in ownerdraw buttons), or you might want to add 
  1308. functionality via usability enhancements (as in ownerdraw listboxes which 
  1309. contain icons).  As more controls are developed with ownerdraw capability, more 
  1310. uses will be found for this newly created functionality (or is it the second 
  1311. that drives the first...?). 
  1312.  
  1313. The last sentence has a double-edged blade, unfortunately.  Since there are 
  1314. more than a few controls with this capability, there can be no standard way of 
  1315. implementing ownerdrawing.  The specifics are tightly bound to the type of the 
  1316. control which is being "ownerdrawn."  For buttons, the owner receives a 
  1317. WM_CONTROL message with the notification BN_PAINT when the button needs to be 
  1318. drawn, as an example. 
  1319.  
  1320. Introduction to PM Programming - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1321.  
  1322.  
  1323. ΓòÉΓòÉΓòÉ 5.3. Heeeeere's Johnny ΓòÉΓòÉΓòÉ
  1324.  
  1325. Heeeeere's Johnny 
  1326.  
  1327. Now that we aren't complete idiots <grin> with regard to ownerdraw windows, we 
  1328. can look at the sample code to see what secrets it holds.  The application 
  1329. isn't complicated - there is a main() function which displays a dialog box. 
  1330. That's it.  But the dialog box procedure is more complicated than what we have 
  1331. seen up to this point in the column. 
  1332.  
  1333. MRESULT EXPENTRY buttonDlgProc(HWND hwndWnd,
  1334.                                ULONG ulMsg,
  1335.                                MPARAM mpParm1,
  1336.                                MPARAM mpParm2)
  1337. {
  1338.    PBTNDLGINFO pbdiInfo;
  1339.  
  1340.    pbdiInfo=(PBTNDLGINFO)WinQueryWindowPtr(hwndWnd,0);
  1341.  
  1342.    switch (ulMsg) {
  1343.    case WM_INITDLG:
  1344.       {
  1345.          HPS hpsWnd;
  1346.  
  1347.          //----------------------------------------------------------------
  1348.          // Get the dialog's instance data and set it in the window words
  1349.          //----------------------------------------------------------------
  1350.          pbdiInfo=(PBTNDLGINFO)PVOIDFROMMP(mpParm2);
  1351.          WinSetWindowPtr(hwndWnd,0,pbdiInfo);
  1352.  
  1353.          //----------------------------------------------------------------
  1354.          // Load the bitmaps
  1355.          //----------------------------------------------------------------
  1356.          hpsWnd=WinGetPS(hwndWnd);
  1357.  
  1358.          pbdiInfo->hbmOkUp=GpiLoadBitmap(hpsWnd,
  1359.                                          NULLHANDLE,
  1360.                                          BMP_OKUP,
  1361.                                          0,
  1362.                                          0);
  1363.          pbdiInfo->hbmOkDown=GpiLoadBitmap(hpsWnd,
  1364.                                            NULLHANDLE,
  1365.                                            BMP_OKDOWN,
  1366.                                            0,
  1367.                                            0);
  1368.          pbdiInfo->hbmCancelUp=GpiLoadBitmap(hpsWnd,
  1369.                                              NULLHANDLE,
  1370.                                              BMP_CANCELUP,
  1371.                                              0,
  1372.                                              0);
  1373.          pbdiInfo->hbmCancelDn=GpiLoadBitmap(hpsWnd,
  1374.                                              NULLHANDLE,
  1375.                                              BMP_CANCELDN,
  1376.                                              0,
  1377.                                              0);
  1378.  
  1379.          WinReleasePS(hpsWnd);
  1380.  
  1381.          //----------------------------------------------------------------
  1382.          // Set the default state of the dialog
  1383.          //----------------------------------------------------------------
  1384. /* @1 */ WinSendDlgItemMsg(hwndWnd,
  1385.                            DBT_CB_ENABLEGROUP,
  1386.                            BM_SETCHECK,
  1387.                            MPFROMSHORT(TRUE),
  1388.                            0);
  1389.       }
  1390.       break;
  1391.    case WM_DESTROY:
  1392.       //-------------------------------------------------------------------
  1393.       // Cleanup
  1394.       //-------------------------------------------------------------------
  1395.       GpiDeleteBitmap(pbdiInfo->hbmOkUp);
  1396.       GpiDeleteBitmap(pbdiInfo->hbmOkDown);
  1397.       GpiDeleteBitmap(pbdiInfo->hbmCancelUp);
  1398.       GpiDeleteBitmap(pbdiInfo->hbmCancelDn);
  1399.       break;
  1400.    case WM_CONTROL:
  1401.       switch (SHORT1FROMMP(mpParm1)) {
  1402.       case DBT_CB_ENABLEGROUP:
  1403.          switch (SHORT2FROMMP(mpParm1)) {
  1404.          case BN_CLICKED:
  1405.          case BN_DBLCLICKED:
  1406.             {
  1407.                BOOL bChecked;
  1408.  
  1409.                //----------------------------------------------------------
  1410.                // Get the check state of the window and enable or disable
  1411.                // the radio button group appropriately.
  1412.                //----------------------------------------------------------
  1413. /* @2 */       bChecked=SHORT1FROMMP(WinSendDlgItemMsg(hwndWnd,
  1414.                                                        DBT_CB_ENABLEGROUP,
  1415.                                                        BM_QUERYCHECK,
  1416.                                                        0,
  1417.                                                        0));
  1418.                WinEnableWindow(WinWindowFromID(hwndWnd,DBT_RB_CHOICE1),
  1419.                                bChecked);
  1420.                WinEnableWindow(WinWindowFromID(hwndWnd,DBT_RB_CHOICE2),
  1421.                                bChecked);
  1422.             }
  1423.             break;
  1424.          default:
  1425.             return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  1426.          } /* endswitch */
  1427.          break;
  1428.       case DBT_UB_OK:
  1429.       case DBT_UB_CANCEL:
  1430.          switch (SHORT2FROMMP(mpParm1)) {
  1431.          case BN_PAINT:
  1432.             {
  1433.                PUSERBUTTON pubButton;
  1434.                HBITMAP hbmDraw;
  1435.                RECTL rclWnd;
  1436.                BITMAPINFOHEADER2 bmihInfo;
  1437.                POINTL ptlPoint;
  1438.  
  1439.                //----------------------------------------------------------
  1440.                // Get the USERBUTTON structure so that we can paint
  1441.                // ourselves properly.
  1442.                //----------------------------------------------------------
  1443. /* @3 */       pubButton=(PUSERBUTTON)PVOIDFROMMP(mpParm2);
  1444.  
  1445.                if (pubButton->fsState==BDS_HILITED) {
  1446.                   if (SHORT1FROMMP(mpParm1)==DBT_UB_OK) {
  1447.                      hbmDraw=pbdiInfo->hbmOkDown;
  1448.                   } else {
  1449.                      hbmDraw=pbdiInfo->hbmCancelDn;
  1450.                   } /* endif */
  1451.                } else {
  1452.                   if (SHORT1FROMMP(mpParm1)==DBT_UB_OK) {
  1453.                      hbmDraw=pbdiInfo->hbmOkUp;
  1454.                   } else {
  1455.                      hbmDraw=pbdiInfo->hbmCancelUp;
  1456.                   } /* endif */
  1457.                } /* endif */
  1458.  
  1459.                //----------------------------------------------------------
  1460.                // Center the bitmap within the window
  1461.                //----------------------------------------------------------
  1462. /* @4 */       WinQueryWindowRect(pubButton->hwnd,&rclWnd);
  1463.  
  1464.                bmihInfo.cbFix=16;
  1465.                GpiQueryBitmapInfoHeader(hbmDraw,&bmihInfo);
  1466.  
  1467.                ptlPoint.x=rclWnd.xRight/2-bmihInfo.cx/2;
  1468.                ptlPoint.y=rclWnd.yTop/2-bmihInfo.cy/2;
  1469.  
  1470.                //----------------------------------------------------------
  1471.                // Draw the bitmap
  1472.                //----------------------------------------------------------
  1473.                WinDrawBitmap(pubButton->hps,
  1474.                              hbmDraw,
  1475.                              NULL,
  1476.                              &ptlPoint,
  1477.                              0,
  1478.                              0,
  1479.                              DBM_NORMAL);
  1480.             }
  1481.             break;
  1482.          default:
  1483.             return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  1484.          } /* endswitch */
  1485.          break;
  1486.       } /* endswitch */
  1487.       break;
  1488.    case WM_COMMAND:
  1489.       switch (SHORT1FROMMP(mpParm1)) {
  1490.       case DBT_UB_OK:
  1491.       case DID_OK:
  1492.          {
  1493.             SHORT sChecked;
  1494.  
  1495.             //-------------------------------------------------------------
  1496.             // Query the tri-state checkbox to see if we should beep.
  1497.             // If in "halftoned" state, assume that means "don't care"
  1498.             // and beep anyway.
  1499.             //-------------------------------------------------------------
  1500. /* @5 */    sChecked=SHORT1FROMMP(WinSendDlgItemMsg(hwndWnd,
  1501.                                                     DBT_3B_WANTBEEP,
  1502.                                                     BM_QUERYCHECK,
  1503.                                                     0,
  1504.                                                     0));
  1505.  
  1506.             switch (sChecked) {
  1507.             case 0:
  1508.                break;
  1509.             case 1:
  1510.                WinAlarm(HWND_DESKTOP,WA_NOTE);
  1511.                break;
  1512.             case 2:
  1513.                WinAlarm(HWND_DESKTOP,WA_ERROR);
  1514.                break;
  1515.             default:
  1516.                break;
  1517.             } /* endswitch */
  1518.  
  1519.             WinDismissDlg(hwndWnd,TRUE);
  1520.          }
  1521.          break;
  1522.       case DBT_UB_CANCEL:
  1523.       case DID_CANCEL:
  1524.          WinDismissDlg(hwndWnd,FALSE);
  1525.          break;
  1526.       case DBT_PB_BEEPNOW:
  1527.          WinAlarm(HWND_DESKTOP,WA_NOTE);
  1528.          break;
  1529.       default:
  1530.          return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  1531.       } /* endswitch */
  1532.       break;
  1533.    default:
  1534.       return WinDefDlgProc(hwndWnd,ulMsg,mpParm1,mpParm2);
  1535.    } /* endswitch */
  1536.  
  1537.    return MRFROMSHORT(FALSE);
  1538. }
  1539.  
  1540. When you stop to look at it, there are only four messages that are processed: 
  1541. WM_INITDLG and WM_DESTROY for initialization and termination of the dialog box, 
  1542. WM_CONTROL to control the execution path of the dialog box, and WM_COMMAND to 
  1543. process the final result of the dialog box. 
  1544.  
  1545. Landmarks Again 
  1546.  
  1547. Look at landmark @1; here, we manually set the check state of the button.  Why? 
  1548. If you try the application, you'll see that this checkbox controls whether or 
  1549. not the radio buttons are enabled.  If we do not send the BM_SETCHECK message, 
  1550. the checkbox will not be checked (by default) but the radio buttons will be 
  1551. enabled and this doesn't make sense semantically. 
  1552.  
  1553. At landmark @2, you find that we have to query the button ourselves to see if 
  1554. it is checked before we can proceed.  This has always been one of my pet-peeves 
  1555. since it should make sense to provide this information to the application in 
  1556. this message. 
  1557.  
  1558. Skip to landmark @5 where we find the same BM_QUERYCHECK message as in the 
  1559. WM_CONTROL notification. The reason for pointing it out here is to demonstrate 
  1560. that tri-state buttons return a 0, 1, or 2 to indicate unchecked, checked, or 
  1561. half-toned state. 
  1562.  
  1563. Back at landmark @3 we see the ownerdrawing code.  Button controls pass a 
  1564. pointer to a USERBUTTON structure in mpParm2 for the BN_PAINT notification. 
  1565.  
  1566. typedef struct _USERBUTTON {
  1567.    HWND hwnd;
  1568.    HPS hps;
  1569.    ULONG fsState;
  1570.    ULONG fsStateOld;
  1571. } USERBUTTON, *PUSERBUTTON;
  1572.  
  1573. hwnd is the handle to the button, hps is the handle to the presentation space 
  1574. in which you are to draw, fsState and fsStateOld describe the current and 
  1575. previous state of the button as a BDS_* constant: 
  1576.  
  1577. BDS_HILITED         The button is depressed. 
  1578. BDS_DEFAULT         The button is the default pushbutton. 
  1579. BDS_DISABLED        The button is disabled. 
  1580.  
  1581. Note that the explanation for BDS_DEFAULT implies that an ownerdraw button is 
  1582. really a pushbutton incognito. 
  1583.  
  1584. During the notification, we obtain the pointer to this structure, check the 
  1585. value of fsState, and draw ourselves appropriately at landmark @4.  This final 
  1586. one, I will ask you to save for a later time. 
  1587.  
  1588. Introduction to PM Programming - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1589.  
  1590.  
  1591. ΓòÉΓòÉΓòÉ 5.4. Conclusion ΓòÉΓòÉΓòÉ
  1592.  
  1593. Conclusion 
  1594.  
  1595. Our conclusion is simple:  the button control isn't fooling anyone by looking 
  1596. complex.  In fact, it is a rather unintimidating control.  We also looked at 
  1597. what an ownerdraw control is and how is applies specifically to buttons.  As we 
  1598. dissect other controls with this capability, we will learn how the 
  1599. functionality can be utilized. 
  1600.  
  1601. Next month, we will begin looking at our next window class - the listbox. 
  1602.  
  1603. Introduction to PM Programming - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1604.  
  1605.  
  1606. ΓòÉΓòÉΓòÉ 6. Contributors to this Issue ΓòÉΓòÉΓòÉ
  1607.  
  1608. Are You a Potential Author? 
  1609.  
  1610. We are always looking for (new) authors.  If you have a topic about which you 
  1611. would like to write, send a brief description of the topic electronically to 
  1612. any of the editors, whose addresses are listed below, by the 15th of the month 
  1613. before the month in which your article will appear.  This alerts us that you 
  1614. will be sending an article so that we can plan the issue layout accordingly. 
  1615. After you have done this, get the latest copy of the Article Submission 
  1616. Guidelines from ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory. 
  1617. (The file is artsub.zip.)  The completed text of your article should be sent to 
  1618. us no later than five days prior to the last day of the month; any articles 
  1619. received after that time may be pushed to the next issue. 
  1620.  
  1621. The editors can be reached at the following email addresses: 
  1622.  
  1623. o Larry Salomon - os2man@panix.com (Internet). 
  1624. o Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet). 
  1625.  
  1626. The following people contributed to this issue in one form or another (in 
  1627. alphabetical order): 
  1628.  
  1629. o Larry Salomon, Jr. 
  1630. o Carsten Whimster 
  1631. o Gordon Zeglinski 
  1632. o Network distributors 
  1633.  
  1634. Contributors - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1635.  
  1636.  
  1637. ΓòÉΓòÉΓòÉ 6.1. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  1638.  
  1639. Larry Salomon, Jr. 
  1640.  
  1641. Larry Salomon, Jr. wrote his first Presentation Manager application for OS/2 
  1642. version 1.1 in 1989.  Since that time, he has written numerous VIO and PM 
  1643. applications, including the Scramble applet included with OS/2 and the 
  1644. I-Brow/Magnify/Screen Capture trio being distributed by IBM with the 
  1645. Professional Developers Kit CD-ROM.  Currently, he works for Cheyenne Software 
  1646. in Roslyn, New York and resides in Bellerose, New York with his wife Lisa. 
  1647.  
  1648. Larry can be reached electronically via the Internet at os2man@panix.com. 
  1649.  
  1650. Contributors - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1651.  
  1652.  
  1653. ΓòÉΓòÉΓòÉ 6.2. Carsten Whimster ΓòÉΓòÉΓòÉ
  1654.  
  1655. Carsten Whimster 
  1656.  
  1657. Carsten is an undergraduate Computer Science student at the University of 
  1658. Waterloo.  He is currently in third year, and enjoying it. 
  1659.  
  1660. Carsten is a beginning OS/2 PM programmer with a few projects on the go. He 
  1661. uses Watcom C/C++ 10.0 and Watcom VX-REXX 2.0b. 
  1662.  
  1663. Carsten is the author of POV-Panel/2, a popular shareware dashboard-like 
  1664. front-end for the POV-Ray 2.x compilers.  It can be found on ftp-os2.cdrom.com 
  1665. in pub/os2/32bit/graphics and some of the other major OS/2 ftp sites.  He is 
  1666. also a TEAM-OS/2 member, and has adopted a little store in Waterloo. 
  1667.  
  1668. You may reach Carsten... 
  1669.  
  1670. ...via email: 
  1671.  
  1672. bcrwhims@undergrad.math.uwaterloo.ca  - Internet 
  1673.  
  1674. ...via snail mail (notice the changed address): 
  1675.  
  1676. Carsten Whimster
  1677. 318A Spruce Street
  1678. Waterloo, Ontario
  1679. Canada
  1680. N2L 3M7
  1681.  
  1682. Contributors - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1683.  
  1684.  
  1685. ΓòÉΓòÉΓòÉ 6.3. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  1686.  
  1687. Gordon Zeglinski 
  1688.  
  1689. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  1690. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  1691. He has been programming in C++ for 6 years and also has a strong background in 
  1692. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  1693.  
  1694. His current projects include a client/server communications program that 
  1695. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  1696. involved in the development of a "real-time" automated vehicle based on OS/2 
  1697. and using C++ in which he does device driver development and designs the 
  1698. applications that comprise the control logic and user interface. 
  1699.  
  1700. He can be reached via the Internet at zeglins@cc.umanitoba.ca. 
  1701.  
  1702. Contributors - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1703.  
  1704.  
  1705. ΓòÉΓòÉΓòÉ 6.4. Network distributors ΓòÉΓòÉΓòÉ
  1706.  
  1707. Network Distributors 
  1708.  
  1709. These people are part of our distribution system to provide EDM/2 on networks 
  1710. other than the Internet.  Their help to provide access to this magazine for 
  1711. others is voluntary and we appreciate them a lot! 
  1712.  
  1713. o Paul Hethmon (hethmon@apac.ag.utk.edu) - Compuserve 
  1714. o Gess Shankar (gess@knex.mind.org) - Internet 
  1715. o David Singer (singer@almaden.ibm.com) - IBM Internal 
  1716. o Andre Asselin (ASSELIN AT RALVM12) - IBM Internal 
  1717.  
  1718. If you would like to become a "network distributor", be sure to contact the 
  1719. editors so that we can give you the credit you deserve! 
  1720.  
  1721. Contributors - EDM/2 - Nov 1994 - Volume 2, Issue 10 
  1722.  
  1723.  
  1724. ΓòÉΓòÉΓòÉ 7. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  1725.  
  1726. How Do I Get EDM/2? 
  1727.  
  1728. EDM/2 can be obtained in any of the following ways: 
  1729.  
  1730. On the Internet 
  1731.  
  1732. o All back issues are available via anonymous FTP from the following sites: 
  1733.  
  1734.    - ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory. 
  1735.    - ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  1736.    - generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  1737.  
  1738. o The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org to 
  1739.   receive a file containing (among other things) instructions for subscribing 
  1740.   to EDM/2.  This is a UUCP connection, so be patient please. 
  1741. o IBM's external gopher/WWW server in Almaden. The address is 
  1742.   index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of the 
  1743.   "OS/2 Information" menu; the URL is 
  1744.   "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70". 
  1745.  
  1746. On Compuserve 
  1747.  
  1748. All back issues are available in the OS/2 Developers Forum 2. 
  1749.  
  1750. IBM Internal 
  1751.  
  1752. o IBM's internal gopher/WWW server in Almaden. The address is 
  1753.   n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu; the 
  1754.   URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70". 
  1755. o IBM's REQUEST command on all internal VM systems.  Enter the VM command 
  1756.   REQUEST LIST FROM ASSELIN AT RALVM12 and a list of the requestable packages 
  1757.   will be sent to you; in this list are the names of the packages containing 
  1758.   the EDM/2 issues. 
  1759.  
  1760. How do I Get EDM/2? - EDM/2 - Nov 1994 - Volume 2, Issue 10