home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 32 Periodic / 32-Periodic.zip / edm38.zip / EDMI3-8.INF (.txt)
OS/2 Help File  |  1995-09-10  |  308KB  |  4,133 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Sept 1995 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                   The Electronic Developer's Magazine for OS/2
  5.                       Portions copyright (c) by IQPac Inc.
  6.                                 Volume 3, issue 8
  7.  
  8. The New York Times Fiasco 
  9.  
  10. If you haven't been in this dimension in the past month, you probably don't 
  11. know about the two articles printed by the New York Times and the ensuing 
  12. fallout.  In a nutshell, the Times printed one article about the annual meeting 
  13. that IBM has with market analysts in which they severely misinterpreted Lou 
  14. Gerstner's statements.  While IBM claims that he was simply reiterating the 
  15. strategy that IBM has had for the past five or so years (although with a 
  16. stronger emphasis), the `Times inferred that he was conceding the desktop to 
  17. Microsoft. 
  18.  
  19. The following week, Peter Lewis - in his Science Times column - quoted David 
  20. Barnes as saying that he'll run Windows 95 at home instead of OS/2.  It hurt so 
  21. much to read that one week after the first article that I and many others 
  22. immediately started shouting conspiracy and went witch- hunting.  In 
  23. retrospect, it really shouldn't matter what David Barnes runs at home; he still 
  24. is the best OS/2 spokesman IBM has.  However, I can't help but feel like I just 
  25. found out that Michael Jordan really wears ProKeds. 
  26.  
  27. For more information, there are many places on the Web that you can visit; one 
  28. of these is http://www.inetnw.com/~os2man.  Enjoy. 
  29.  
  30. More About the Web Site 
  31.  
  32. If you haven't dropped by the EDM/2 Web site 
  33. (http://os2man.netsysdev.telerate.com), you are missing some interesting 
  34. things.  The Gotcha section is growing very slowly, but growing nonetheless. 
  35. Additionally, a new section has been added which allows you to do conferencing, 
  36. a la Netnews.  This section, powered by the FORAWEB software that I wrote in 
  37. REXX for GoServe, has the advantages that it is easy to setup, doesn't require 
  38. a newsfeed to run, and is relatively instantaneous.  The main disadvantage, 
  39. however, is that each server is self-contained; there is no shadowing 
  40. capability (although this is definitely something that needs looking into). 
  41.  
  42. To read the articles posted, you simply need a Web browser.  (Lynx will work 
  43. too if you use http://os2man.netsysdev.telerate.com/FLIST.CMD?FORA as the URL.) 
  44. To submit an article to a conference, your Web browser must have HTML forms 
  45. capability. 
  46.  
  47. One of the existing conferences is for the discussion of EDM/2.  Please drop by 
  48. and contribute your thoughts, comments, etc.! 
  49.  
  50. Transparent Windows and Such 
  51.  
  52. This month, I vowed to write the article on the transparency that I have 
  53. claimed to achieved.  Before the transparency must come the samples, though. I 
  54. had no trouble getting the desired effect, but when I went to write another 
  55. sample to demonstrate how PM `normally' operates, two (bad) things happened: 
  56.  
  57.    1. The `non-transparent' application had the sample look. 
  58.    2. When I removed the CS_SIZEREDRAW class style from the parent of the 
  59.       window (the client), the window disappeared. 
  60.  
  61.  The second came about from my attempt to coerce the second sample to not look 
  62.  like the first.  I think that, if I painted the client window in something 
  63.  other than a solid color, it would make a difference.  However, more 
  64.  investigation is needed before I can write about this topic and I offer my 
  65.  apologies for this.  In the meantime, I would guess that avoiding any calls to 
  66.  WinFillRect() or GpiErase() may be used to reach the same goal. 
  67.  
  68.  EDM/2 A La Postscript 
  69.  
  70.  I fully intend, as I sit here to type in this section, to produce a Postscript 
  71.  version of this issue.  Whether or not this becomes a reality will be 
  72.  discovered shortly.  This will be a bit more time-consuming because normally I 
  73.  send to Carsten (my proofreader) an .INF file and make the corrections 
  74.  indicated by him to the .IPF source directly.  However, I must now send him a 
  75.  .RTF file and hope that it shows up properly on his side. Additionally, he 
  76.  will no longer be able to check things such as the icons and such.  The result 
  77.  of all of this is that we might be a bit shaky in the quality of the issues 
  78.  while we adjust our procedures.  Please bear with us. 
  79.  
  80.  "How Will I Read the Issues?" 
  81.  
  82.  When the magazine eventually switches to Postscript as the file format, 
  83.  instead of .INF, how will you read it?  Some time ago, IQPac reached an 
  84.  agreement with Magus Software to allow IQPac to distribute a customized 
  85.  version of their PageTurner software (sans documentation, unfortunately), 
  86.  which is a Postscript viewer.  This version will only allow you to view 
  87.  Postscript files that I produce using an encrypted password mechanism that is 
  88.  imbedded in the file.  The problem has always been that of distribution; since 
  89.  IQPac is currently a no-income company, I am trying to keep my costs down. The 
  90.  ideal distribution mechanism is through diskette mailers, but the miracle of 
  91.  the Web makes that more expensive than necessary. 
  92.  
  93.  The idea `du jour' is that those who are Web capable will be able to fill out 
  94.  an HTML form on the EDM/2 site.  Completion of the form will assign you a 
  95.  userid and password - valid for that day only - which you can use to obtain 
  96.  access to a protected section of the site.  There you will be able to download 
  97.  the software.  For those of you who are not Web capable, I will provide a form 
  98.  for you to fill out and send to me along with a money order (drawable on US 
  99.  funds) to cover shipping costs. 
  100.  
  101.  I apologize for my insistence that you fill out the form, but this information 
  102.  is vital to obtaining (somewhat) accurate statistics on the number of readers 
  103.  that EDM/2 has.  With this information, a press kit can be constructed and 
  104.  delivered to ISVs and advertising space sold.  This income will be used to 
  105.  offer some amount of compensation to the future contributors of articles, 
  106.  columns, and (of course) me.  It doesn't take a rocket-science degree to 
  107.  figure this out on your own, but I am revealing it to you in order to keep a 
  108.  clean conscience.  We have all given much time and effort to insure a good 
  109.  magazine filled with good information; please support us in this by 
  110.  cooperating instead of trying to circumvent the measures I will have 
  111.  established to achieve this goal.  Please keep in mind that EDM/2 will still 
  112.  be distributed free-of-charge to the readers. 
  113.  
  114.  I am interested in any thoughts you have on this matter - feel free to send 
  115.  them to os2man@panix.com. 
  116.  
  117.  OOPS Corner Will Be Absent 
  118.  
  119.  Because Gordon has devoted a lot of time to doing the excellent reviews on the 
  120.  C++ compilers, he has not had enough time to write this month's OOPS Corner. 
  121.  We think that it is a fair trade. 
  122.  
  123.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  124.  
  125.  
  126. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  127.  
  128. Copyright Notice 
  129.  
  130. EDM/2 is published by IQPac Inc.  IQPac Inc.  can be reached via U.S. Mail at 
  131. the following address: 
  132.  
  133. IQPac Inc.
  134. 7 East Broadway, Box 804
  135. New York, NY 10038
  136. U.S.A.
  137.  
  138.  Editor-in-chief               Larry Salomon Jr. 
  139.  Associate editor              Carsten Whimster 
  140.  Contributing editor           Gordon Zeglinski 
  141.  
  142.  CEO/President                 Larry Salomon Jr. 
  143.  
  144.  All material is copyrighted by its original author.  No part of this magazine 
  145.  may be reproduced without permission from the original author. 
  146.  
  147.  This publication may be freely distributed in electronic form provided that 
  148.  all parts are present in their original unmodified form.  A reasonable fee may 
  149.  be charged for the physical act of distribution; no fee may be charged for the 
  150.  publication itself. 
  151.  
  152.  Neither IQPac Inc.  nor this publication are affiliated with International 
  153.  Business Machines Corporation. 
  154.  
  155.  OS/2 is a registered trademark of International Business Machines Corporation. 
  156.  Other trademarks are property of their respective owners.  Any mention of a 
  157.  product in this publication does not constitute an endorsement or affiliation 
  158.  unless specifically stated in the text. 
  159.  
  160.  The OS/2 Accredited Logo is a trademark of International Business Machines 
  161.  Corporation and is used by IQPac Inc.  under license.  This On-line 
  162.  Publication is independently produced by IQPac Inc.  and IBM is not 
  163.  responsible in any way for its contents. 
  164.  
  165.  IQPac Inc.  is an accredited member of the IBM Independent Vendor League. 
  166.  
  167.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  168.  
  169.  
  170. ΓòÉΓòÉΓòÉ 3. Announcements ΓòÉΓòÉΓòÉ
  171.  
  172. Announcements 
  173.  
  174. Rock Solid Software Announces IOPRO/VX 
  175.  
  176. Rock Solid Software announces IOPRO/VX, a toolkit designed to support the rapid 
  177. development of data acquisition, analysis, and control applications under OS/2. 
  178.  
  179. Thank you for allowing us to describe our line of technical productivity tools 
  180. for the OS/2 environment.  Our mission is to support our customers in creating 
  181. in a wide variety of data acquisition, data analysis, process monitoring and 
  182. control, and data visualization applications.  IOPRO/VX is simply the first 
  183. product in our plan to get the most out of this superior operating system. 
  184. Coming soon: 
  185.  
  186.      Notebook data acquisition (PCMCIA). 
  187.      Imaging and image analysis. 
  188.      DSP coprocessing. 
  189.      Embedded applications. 
  190.  
  191.  Simply put, we are convinced OS/2 is the best operating system in the world 
  192.  for affordable technical computing, data acquisition and analysis, and process 
  193.  monitoring and control.  We are committed to realizing that potential. 
  194.  
  195.  The following information will describe our initial offering, IOPRO/VX. This 
  196.  toolset allows VX-Rexx developers to rapidly build a software program, 
  197.  complete with graphical user interface, which can control the acquisition, 
  198.  processing, display, and saving of data.  This data can come from a variety of 
  199.  sources such as disk files or local A/D- D/A and digital I/O adapter cards. 
  200.  Extensions to the basic package allow accessing data from sources via network 
  201.  connection, or from instrumentation accessed via serial or IEEE-488 
  202.  interfaces. 
  203.  
  204.  The IOPRO/VX basic pak consists of the following: 
  205.  
  206.  The basic pak includes one driver for supported plug in adapter cards. While 
  207.  we are trying to target the most capable and/or popular cards for driver 
  208.  development, we are very willing to discuss how to expedite development for 
  209.  your particular application.  Please call for driver availability and/or to 
  210.  discuss development schedules. 
  211.  
  212.  The main programming toolset comprising the IOPRO/VX package consists of a set 
  213.  of objects which are added to the VX-Rexx toolbar.  These objects are placed 
  214.  into the application being developed using standard VX-Rexx techniques. These 
  215.  objects provide the following functionality: 
  216.  
  217.    1. Disk Input:  import data (in a variety of formats) from disk files. 
  218.  
  219.    2. Disk Output:  export data:  (again, a choice of formats) to disk or to 
  220.       another program on the host machine.  This is also used to move data to 
  221.       the Integrated Data Display utility (see below) for realtime viewing. 
  222.  
  223.    3. Processing:  this class of objects allows analysis or transform 
  224.       operations on data.  There are two basic types.  The first simply allows 
  225.       the developer to write a series of REXX statements which can operate on 
  226.       the data. The second type acts as a link to some function residing in an 
  227.       external function (C,C++,etc.)  library. 
  228.  
  229.    4. I/O Channel Interface:  this class presents a standard interface to 
  230.       analog to digital converters, digital inputs, digital outputs, counters, 
  231.       etc.  The basic pak supports data originating locally, as from an I/O 
  232.       adapter card plugged into the host machine.  Optional extensions allow 
  233.       access to data originating on other machines and accessed via a network, 
  234.       or from instrumentation via RS-232 or IEEE-488. 
  235.  
  236.    5. Data Display Utility:  this facility is used to display graphical plots 
  237.       of data exported from the IOPRO/VX environment.  It is implemented as a 
  238.       process which runs independent from the VX-Rexx session.  The DDU has 
  239.       it's own set of PM based controls which are used to control plotting 
  240.       behavior such as graph scaling, axis labels, etc. 
  241.  
  242.    6. System Control and Sequencing:  this object acts as the 'main control 
  243.       loop' found in so many applications of this type.  It is basically a set 
  244.       of event handling routines, where upon receipt of an event 'x', a user 
  245.       definable set of REXX statements is executed.  These statements can 
  246.       invoke methods on the other objects to cause I/O channels to be read or 
  247.       written, processing to occur on some buffer of data, etc.  The SCS can 
  248.       react to events from user activity, timer input, receipt of data from one 
  249.       of the remote connections, or from an interrupt generated by a local I/O 
  250.       adapter card. 
  251.  
  252.  This product is about to enter beta testing and should be available by Fall 
  253.  95. 
  254.  
  255.  Look for our survey in the following locations: 
  256.  
  257.   Internet:  comp.os.os2.programmer.tools
  258.   Compuserve:  OS2USER OPEN FORUM
  259.  
  260.  Please direct inquiries to the following: 
  261.  
  262.   Rock Solid Software
  263.   8460 Plank Rd.
  264.   Montville OH 44064
  265.   (216)-390-0590
  266.  
  267.   76016.370@compuserve.com
  268.  
  269.  ____________________________________________________________ 
  270.  
  271.  Secant Technologies Announces ObjectPM Control Pack 
  272.  
  273.   Additional info: http://www.secant.com
  274.   Questions to: info@secant.com
  275.   For more information: John Pompeii (216) 595-3830
  276.  
  277.  CLEVELAND, OH -- Secant Technologies, Inc.  announces the release of the 
  278.  ObjectPM Control Pack library for OS/2.  This package offers over a dozen 
  279.  control types that extend the set of controls supplied by OS/2 Presentation 
  280.  Manager.  It is also the first control package to support the PMCX control 
  281.  window specification allowing these controls to be used with products such as 
  282.  the IBM Universal Resource Editor and Prominare Designer.  The PMCX 
  283.  specification is the latest control extension similar in concept to the VBX 
  284.  specification in Windows. 
  285.  
  286.  "These controls will be a welcome addition to any OS/2 programmer's tool set" 
  287.  according to senior architect Michael Flis.  "Many badly needed features such 
  288.  as multi-column list- boxes and edit masks are missing from OS/2.  This 
  289.  product fills those gaps." 
  290.  
  291.  This list of controls included with the package include: 
  292.  
  293.      Spreadsheet - A "grid" control allowing data to be presented in rows and 
  294.       columns.  The rows and columns can be sized hidden, inserted and deleted. 
  295.       Cells can directly edited, and support character formatting. 
  296.  
  297.      Cellbox - A new list-box that adds multi-columns, images, "hot buttons", 
  298.       and in-line character formatting. 
  299.  
  300.      Data Field - An edit control extension that supports edit masks, and a 
  301.       host of data types. 
  302.  
  303.      RTF Viewer - Displays and prints Rich-Text-Format (RTF) documents.  This 
  304.       is a great tool to add prining capabilities to your apps! 
  305.  
  306.      Calendars - Displays a calendar, one month at a time, allowing a user to 
  307.       click on a day to select it or flip between months and years. 
  308.  
  309.      DateComboBox - Combines a combo-box with the calendar control which 
  310.       implements a visual drop-down date field. 
  311.  
  312.      CellComboBox - Combines a combo-box with the cellbox to add extended 
  313.       combo features such as multi-selects and list-box columns. 
  314.  
  315.      Splitbars - Horizontal and vertical split bar controls for dragging. 
  316.  
  317.      ControlList - Contains a list of other controls that can be scrolled up 
  318.       and down.  This allows a large number of controls to fit in an area than 
  319.       otherwise would be possible. 
  320.  
  321.      Gauges - A set of various indicators such as dials, thermometers, and LED 
  322.       bars. 
  323.  
  324.  All controls in ObjectPM Control Pack conform to the PMCX architecture. This 
  325.  allows the components to be used by virtually any OS/2 programming tool. To 
  326.  support the various C++ programming environments, the Control Pack adds a set 
  327.  of class libraries that integrate the controls natively into the OpenClass 
  328.  (IBM), ObjectWindows (Borland), and ObjectPM (Secant) application framework 
  329.  environments. 
  330.  
  331.  The ObjectPM Control Pack is available in binary form at an introductory price 
  332.  of $99.  Source code is also available.  Programs that use the controls can be 
  333.  distributed along with the run-time libraries without royalties or additional 
  334.  purchases.  To order, contact Secant Technologies, 23811 Chagrin Blvd.  Suite 
  335.  344, Beachwood, OH, (216) 595-3830.  Additional information and samples are 
  336.  available from the Secant World Wide Web home page at http://www.secant.com, 
  337.  or email at info@secant.com. 
  338.  
  339.  ObjectPM is a trademark of Secant Technologies, Inc.  OS/2 and Presentation 
  340.  Manager are registered trademarks of International Business Machines 
  341.  Corporation Microsoft Windows is a registered trademark of Microsoft 
  342.  Corporation 
  343.  
  344.  ____________________________________________________________ 
  345.  
  346.  REXX/SQL - A REXX interface to SQL databases 
  347.  
  348.  General 
  349.  
  350.  REXX/SQL provides a simple interface for REXX programs to access SQL databases 
  351.  through a number of external functions.  REXX/SQL is intended to provide a 
  352.  consistant interface to all SQL databases. 
  353.  
  354.  REXX/SQL is distributed under the GNU General Public License.  See the file 
  355.  COPYING for more details.  The anon ftp site for REXX/SQL is: 
  356.  ftp.qut.edu.au/src/REXXSQL. 
  357.  
  358.  The source code for each database interface code is in a separate archive 
  359.  file.  The general format of the archive files is:  rxsql???nn.ext 
  360.  
  361.  where: 
  362.  
  363.  ???  is the TLA for the database port, nn is the version number and ext is the 
  364.  archive file type.  e.g.  the REXX/SQL Oracle port for Version 1.2 in 
  365.  compressed tar file format is rxsqlora12.tar.Z. 
  366.  
  367.  Documentation, in Postscript and HTML, is available in rxsqldocnn.ext and 
  368.  sample programs are in rxsqlsamnn.ext. 
  369.  
  370.  The documentation is intended as both a user's guide and a reference guide for 
  371.  implementors of REXX/SQL on other database and operating system platforms. 
  372.  
  373.  All text files are stored in Unix text file format.  ie LF only. 
  374.  
  375.  Current Release 
  376.  
  377.  The current release of REXX/SQL is 1.2.  This version contains ports of 
  378.  REXX/SQL for Oracle (ora) and mSQL (min). 
  379.  
  380.  Files in Release 
  381.  
  382.  The following packages are available in Info-Zip 2.0 format: 
  383.  
  384.   rxsqldoc12.zip - Documentation - Postscript and HTML
  385.   rxsqlsam12.zip - Sample REXX/SQL programs
  386.   rxsqlora12.zip - Oracle source and OS/2 EXE and DLL
  387.   rxsqlmin12.zip - mSQL source
  388.  
  389.  and in compressed tar files 
  390.  
  391.   rxsqldoc12.tar.Z - Documentation - Postscript and HTML
  392.   rxsqlsam12.tar.Z - Sample REXX/SQL programs
  393.   rxsqlora12.tar.Z - Oracle source and OS/2 EXE and DLL
  394.   rxsqlmin12.tar.Z - mSQL source
  395.  
  396.  Please forward any comments, suggestions, enhancements or other 
  397.  implementations to be included in the official distribution. 
  398.  
  399.  The above files are currently in the /incoming directory and will be moved to 
  400.  /src/REXXSQL shortly. 
  401.  
  402.  ____________________________________________________________ 
  403.  
  404.  Functional Software Announces LXOPT version 1.1 
  405.  
  406.  14 August 1995 
  407.  
  408.  Functional Software announces V1.1 of the code optimiser for 32-bit OS/2 
  409.  executables and dynamic link libraries. 
  410.  
  411.  LXOPT (Linear eXecutable OPTimiser) is a unique OS/2 development tool, a code 
  412.  optimiser which improves the layout of 32 bit OS/2 applications by direct 
  413.  manipulation of EXE and DLL files.  Processor instruction sequences are 
  414.  reorganised to minimise page faults and ensure maximum CPU cache efficiency. 
  415.  
  416.  LXOPT V1.1 introduces: 
  417.  
  418.      Improved arrangement algorithms 
  419.      CPU optimisations 
  420.      OS/2 WARP compressed page (exepack:2) support 
  421.      Support for CSet++ V2.x C++ template users 
  422.      Improved support for Borland and Watcom C++ users 
  423.      Recording file size reductions of > 80%. 
  424.  
  425.  In addition LXOPT is now supplied with program utilities to time application 
  426.  execution, simulate low memory conditions, compress V2.x executables to WARP 
  427.  (exepack:2) format and decompress exepack:2 executables for use with OS/2 
  428.  V2.x. 
  429.  
  430.  LXOPT V1.1 has a RRP of USD 195, additional users may be added to an existing 
  431.  license for USD 95.  There are no restrictions or royalties on the 
  432.  distribution of LXOPT V1.1 processed applications.  Registered users receive 
  433.  free maintenance releases and priority technical support. 
  434.  
  435.  A demonstration version of LXOPT V1.1 is available as LXOPT111.ZIP on 
  436.  Compuserve (OS2DF1-Development Tools).  This file is also being distributed to 
  437.  various ftp sites and is now in the incoming directories on ftp.cdrom.com and 
  438.  hobbes.nmsu.edu.  The demo will be added to other sites during the next few 
  439.  days. 
  440.  
  441.  The retail version of LXOPT is available from: 
  442.  
  443.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  444.   ΓöéCountry   ΓöéDistributoΓöéVoice               ΓöéFax                 Γöé
  445.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  446.   ΓöéGermany   ΓöéKessler   Γöé+49 551 50762-0     Γöé+49 551 50762-22    Γöé
  447.   Γöé          ΓöéSoftware  Γöé                    Γöé                    Γöé
  448.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  449.   ΓöéUK        ΓöéGrey      Γöé+44 1364 653499     Γöé+44 1364 653071     Γöé
  450.   Γöé          ΓöéMatter    Γöé                    Γöé                    Γöé
  451.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  452.   Γöé          ΓöéOneStop   Γöé+44 117 985 3370    Γöé+44 117 985 3373    Γöé
  453.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  454.   Γöé          ΓöéOS/2 Soln.Γöé+44 1285 641175     Γöé+44 1285 641661     Γöé
  455.   Γöé          ΓöéCntr.     Γöé                    Γöé                    Γöé
  456.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  457.   ΓöéUSA       ΓöéBMT Micro Γöé+1 800 414 4268     Γöé+1 910 350 2937     Γöé
  458.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  459.  
  460.  LXOPT V1.0 Users 
  461.  
  462.  All registered LXOPT 1.0 users will be upgraded to V1.1 free of charge. Please 
  463.  allow up to 14 days for delivery.  If you have purchased but not registered 
  464.  your copy of V1.0 with Functional Software please do so as soon as possible. 
  465.  
  466.  ____________________________________________________________ 
  467.  
  468.  Developer Connection Volume 8 Is Available 
  469.  
  470.  August 11, 1995 
  471.  
  472.  Today the Developer Connection Volume 8, 2nd Year Anniversary Issue has been 
  473.  completed, and sent to Manufacturing.  This means that our U.S. Developer 
  474.  Connection Subscribers should start receiving it in the next couple weeks, and 
  475.  our International customers soon after. 
  476.  
  477.  The Power of the Future Delivered to Your Door 
  478.  
  479.  The Developer Connection for OS/2 - continuing proof of IBM's commitment to 
  480.  OS/2 developers - can greatly increase your productivity by providing you with 
  481.  the latest tools, pre-release software, product demos, and information you 
  482.  need on today's most convenient medium--a CD.  And, because we live in 
  483.  changing times, an annual subscription to the Developer Connection for OS/2 
  484.  keeps your tools and information from becoming obsolete.  Each year you'll 
  485.  receive 4 volumes including CDs and The Developer Connection News, each packed 
  486.  with the tools and information you need for your OS/2 development efforts. 
  487.  
  488.  When accessed from your CD drive, The Developer Connection for OS/2 becomes a 
  489.  part of your Workplace Shell environment.  Click on The Developer Connection 
  490.  icon, and all the wealth of the Developer Connection for OS/2 is instantly 
  491.  attainable.  Use the powerful Developer Connection Browser to locate any piece 
  492.  of information.  And because the intuitive graphical user interface is a part 
  493.  of the Workplace Shell environment, each task is familiar and simple.  Try the 
  494.  products, install them, or simply retrieve product information.  There is also 
  495.  an available option for creating diskettes for many of the products on the CD. 
  496.  
  497.  The Developer Connection program will continue to grow to support emerging 
  498.  technologies.  Subscribers also receive The Developer Connection for LAN 
  499.  Systems, a cross-platform offering that supports the installation of products 
  500.  and information to OS/2, Windows, DOS, and AIX workstations.  It provides a 
  501.  programming environment for client/server and distributed computing 
  502.  application development.  Device driver developers can now subscribe to The 
  503.  IBM Developer Connection Device Driver Kit for OS/2 (Developer Connection 
  504.  DDK).  The Developer Connection DDK is an annual membership program, that 
  505.  enables rapid development of device drivers for your personal computer 
  506.  hardware using the 32-bit OS/2 operating platform.  Members receive the 
  507.  updated information, test tools and utilities, and many complete device driver 
  508.  sources. 
  509.  
  510.  Put The Developer Connection for OS/2 to work for you...now 
  511.  
  512.      Receive product level versions of OS/2 developer toolkits (for OS/2 2.1, 
  513.       OS/2 Warp Version 3, OS/2 SMP, Pen for OS/2, Mustimedia Presentation 
  514.       Manager, LAN Systems) 
  515.      Receive new versions of operating system technologies as soon as they are 
  516.       developed. 
  517.      Try new OS/2 products before you buy them. 
  518.      Use the sample source code to start on the path of more productive 
  519.       programming. 
  520.      Access pre-release versions of IBM's 32-bit tools to prepare for 
  521.       tomorrow's technology. 
  522.      Receive updates to SMART, One Up Corporation's powerful tool that helps 
  523.       migrate your 16-Bit and 32-Bit Windows code as well as 16-Bit OS/2 code 
  524.       to 32-Bit OS/2 code. 
  525.      Read The Developer Connection News for timely OS/2 information. 
  526.      Access electronic support through the Internet, OS/2 BBS, and CompuServe. 
  527.  
  528.  In the US, you can subscribe to The Developer Connection for OS/2 by calling 
  529.  1-800-6-DEVCON (1-800-633-8266), 303-330- 7655(fax). 
  530.  
  531.  In Canada, call 1-800-561-5293.  1-905-821-1187 (fax) 
  532.  
  533.  In Brazil, call 0800-111205(phone), (011)886-3222(fax) 
  534.  
  535.   In Mexico, call:
  536.   Toll Free: 91-800-00316
  537.   Phone: (525)- 627-1111 in Mexico City.
  538.  
  539.  In other countries, please refer to the table below: 
  540.  
  541.  Country             Telephone 
  542.  Argentina           313-0014 
  543.  Bolivia             35-1840 
  544.  Chile               633-4400 
  545.  Colombia            257-0111 
  546.  Costa Rica          223-6222 
  547.  Ecuador             56-5100 
  548.  El Salvador         98-5011 
  549.  Guatemala           31-5859 
  550.  Honduras            32-2319 
  551.  Panama              639-977 
  552.  Paraguay            444-094 
  553.  Peru                36-6345 
  554.  Dom.Rep.            566-5161 
  555.  Uruguay             923-617 
  556.  Venezuela           908-8901 
  557.  
  558.  To order in Europe, call IBM ISMS Direct Services in Denmark.  Please ensure 
  559.  that you dial the international access code applicable to your country before 
  560.  dialing the appropriate phone number.  Operators speaking the following 
  561.  languages are available.  Note that 45 is the country code for Denmark. 
  562.  
  563.  TeleFax:  Denmark=45 +48142207 
  564.  
  565.  In Asia/Pacific, call:  61-2-354-7684(phone), 61-2-354- 7766(fax). Note that 
  566.  61 is the country code for Australia. 
  567.  
  568.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  569.   ΓöéLanguage       ΓöéDial code      ΓöéNumber         Γöé
  570.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  571.   ΓöéDutch          ΓöéDenmark=45     Γöé+48101400      Γöé
  572.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  573.   ΓöéEnglish        ΓöéDenmark=45     Γöé+48101500      Γöé
  574.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  575.   ΓöéFrench         ΓöéDenmark=45     Γöé+48101200      Γöé
  576.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  577.   ΓöéGerman         ΓöéDenmark=45     Γöé+48101000      Γöé
  578.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  579.   ΓöéItalian        ΓöéDenmark=45     Γöé+48101600      Γöé
  580.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  581.   ΓöéSpanish        ΓöéDenmark=45     Γöé+48101100      Γöé
  582.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  583.   ΓöéDanish         ΓöéDenmark=45     Γöé+48101300      Γöé
  584.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  585.   ΓöéSweden         ΓöéDenmark=45     Γöé+48101150      Γöé
  586.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  587.   ΓöéNorway         ΓöéDenmark=45     Γöé+48101250      Γöé
  588.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  589.   ΓöéFinnish        ΓöéDenmark=45     Γöé+48101650      Γöé
  590.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  591.  
  592.  Prices vary by country.  In the US, an Annual Subscription is $199.00, and an 
  593.  Additional License is $75.00.  These prices do not include shipping and 
  594.  handling. 
  595.  
  596.  ____________________________________________________________ 
  597.  
  598.  DB Technologies' VX-CALENDAR for VX-REXX 
  599.  
  600.  August 14, 1995 
  601.  
  602.  DB Technologies, Inc.  released a calendar object add-on for WATCOM VX-REXX. 
  603.  The "VX-CALENDAR" provides developers with an easy-to-use, intuitive means of 
  604.  viewing date information.  Dates can be moved between the calendar and other 
  605.  objects with drag-and-drop operations.  It also includes support for different 
  606.  colors, fonts, leap years, date navigation through properties and methods, and 
  607.  selection of individual dates. 
  608.  
  609.  The VX-CALENDAR object was written in the C-Language, is SOM- based, and is 
  610.  available from the VX-REXX object toolbar.  The package includes 
  611.  non-exclusive, royalty-free distribution rights.  It is priced at $99.00. 
  612.  Contact DB Technologies, Inc. 
  613.  
  614.   Sales: 800-830-8703
  615.   Tech Support: 941-378-3760
  616.   CompuServe:  72123,3661
  617.   Internet: dbtech@ibm.net
  618.  
  619.  ____________________________________________________________ 
  620.  
  621.  IBM Announces Commonpoint For OS/2 Beta Program 
  622.  
  623.  Advanced object-oriented frameworks from Taligent speed application 
  624.  development 
  625.  
  626.  OBJECT WORLD, SAN FRANCISCO, August 15, 1995...Now OS/2* developers have an 
  627.  important resource for designing, building, and deploying collaborative 
  628.  applications:  IBM CommonPoint** for OS/2*.  This powerful new application 
  629.  system, developed by Taligent, Inc., provides the structural foundation for 
  630.  developers to use object-oriented technology to create and customize 
  631.  distributed business applications, such as client/server, customer support, 
  632.  multimedia, and executive information systems. 
  633.  
  634.  At Object World West '95, IBM announced a "JumpStart" beta program for OS/2 
  635.  developers, which will broaden the reach and accelerate the adoption of 
  636.  cutting-edge CommonPoint technology.  CommonPoint is a rich set of 
  637.  approximately 100 object-oriented frameworks designed to increase programmer 
  638.  productivity through the reuse of application code and design.  CommonPoint's 
  639.  application and system service frameworks, for example, can speed the 
  640.  development and integration of facilities for data translation, data access, 
  641.  collaboration, and other business needs. 
  642.  
  643.  Included in the IBM "JumpStart" program are the CommonPoint Application 
  644.  Development Toolkit for OS/2, a comprehensive set of productivity and resource 
  645.  tools that enable developers to build portable CommonPoint applications; the 
  646.  CommonPoint Application System for OS/2, which enables the deployment of 
  647.  robust CommonPoint applications on the OS/2 platform; and C Set++ for OS/2*, 
  648.  Version 3.0, a fully integrated development environment.  IBM CommonPoint for 
  649.  OS/2 is based on the full-function CommonPoint 1.0 reference release, which 
  650.  was announced by Taligent earlier this year. 
  651.  
  652.  IBM also announced that it has begun delivering IBM CommonPoint on AIX* 
  653.  Version 4, which supports development of portable applications for the 
  654.  leading-edge IBM RISC System/6000 (RS/6000)* platform. 
  655.  
  656.  The CommonPoint for OS/2 announcement expands an extensive portfolio of IBM 
  657.  object-oriented offerings for the enterprise.  IBM's object technology 
  658.  solutions are suited to a variety of skill levels and application types, 
  659.  allowing developers to select the most suitable point of entry into object 
  660.  technology based on their experience, existing systems and tools, and the 
  661.  needs of their customers.  Advanced object-oriented developers, for example, 
  662.  will find CommonPoint useful in developing new C++ applications that are easy 
  663.  to prototype, customize, and maintain. 
  664.  
  665.  "We are excited about starting the early support program for OS/2 shortly 
  666.  after delivering this advanced technology on AIX," said John Slitz, vice 
  667.  president, Object Technologies Marketing, IBM.  "IBM has been at the forefront 
  668.  of helping customers apply object technology to solve business problems. 
  669.  Today's announcement expands this initiative through service and support for 
  670.  the early adoption of CommonPoint's superior object functionality across 
  671.  multiple platforms." 
  672.  
  673.  IBM CommonPoint for OS/2 "JumpStart" Program 
  674.  
  675.  Beta code of the CommonPoint Application System for OS/2 and the CommonPoint 
  676.  Application Development Toolkit for OS/2 will be delivered to corporate 
  677.  developers and independent software vendors participating in the "JumpStart" 
  678.  program, beginning in September 1995.  Product availability is targeted for 
  679.  year-end 1995. 
  680.  
  681.  Comprehensive technical support, education, and consulting services are 
  682.  available to help "JumpStart" customers master developing applications with 
  683.  CommonPoint. 
  684.  
  685.  "IBM now offers cross-platform object technology solutions for everybody, from 
  686.  the neophyte just starting to use class libraries to the experienced object 
  687.  developer who can move up to frameworks with CommonPoint," said Adrian Bowles, 
  688.  managing director, Atelier Research.  "This commitment to object technology -- 
  689.  backed up with real products -- positions IBM as a software development 
  690.  leader." 
  691.  
  692.  During a separate announcement today, Taligent announced it plans to market 
  693.  IBM's CommonPoint for AIX with Taligent services and education under the name 
  694.  CommonPoint ProjectPak -- an integrated set of products and services for 
  695.  corporate developers building their first CommonPoint application. 
  696.  
  697.  For additional information on the "JumpStart" program, contact 
  698.  objtech@vnet.ibm.com via the Internet or access IBM's home page on the World 
  699.  Wide Web at http://www.ibm.com, the IBM software page at 
  700.  http://www.software.ibm.com, or the IBM object technologies page at 
  701.  http://www.software.ibm.com/objects/. 
  702.  
  703.  The IBM CommonPoint application system is based on Taligent Inc.'s CommonPoint 
  704.  application system built using advanced object-oriented frameworks.  Taligent 
  705.  is an independent software company jointly owned by Apple Computer, Inc., 
  706.  Hewlett-Packard Co., and IBM. 
  707.  
  708.  IBM, the world's largest software provider, creates, develops and manufactures 
  709.  the industry's most advanced information technologies, including computer 
  710.  systems, software, networking systems, storage devices and microelectronics. 
  711.  IBM's Software Solutions Division, which has the object technology mission 
  712.  within IBM, provides data management, application development and workgroup 
  713.  solutions for mission-critical applications on PCs, workstations, LANs and 
  714.  host systems. 
  715.  
  716.  * Indicates trademark or registered trademark of International Business 
  717.  Machines Corporation. 
  718.  
  719.  ** Products or companies mentioned are trademarks or registered trademarks of 
  720.  their respective holder. 
  721.  
  722.  ____________________________________________________________ 
  723.  
  724.  TWAIN SDK and DDK For OS/2 
  725.  
  726.  Twain, an industry standard specification for any Twain enabled application to 
  727.  use any Twain supported scanner was acknowleged by IBM as an important 
  728.  workstation standard at the recent May 1995 New Orleans Technical Interchange. 
  729.  A 32 bit, fully Twain compliant implementation is now available for OS/2 
  730.  through Solution Technology, Inc. 
  731.  
  732.  Twain allows any application to use any supported imaging device (camera, 
  733.  scanner, etc).  A special advantage of Twain for OS/2 is its support for 
  734.  almost any resolution image in simple black and white up through 24 bit color 
  735.  without image size restrictions. 
  736.  
  737.  Another advantage of STI's multi-threaded OS/2 implementations of Twain 
  738.  scanner drivers are their ability to scan documents at the full 35-45 pages 
  739.  per minute speed of popular mid range document imaging scanners.  Future 
  740.  versions should push the speed even higher. 
  741.  
  742.  Attached you will find information on Twain for OS/2, Twain for OS/2 SDK and 
  743.  the Twain for OS/2 DDK.  Our two Twain enabled retail applications, Applause 
  744.  and ReView, are available through distribution.  All products are currently 
  745.  available from stock. 
  746.  
  747.  The SDK will allow you to write the interface between your application and the 
  748.  TWAIN.DLL for OS/2.  The SDK comes with all the required and optional DLL's, 
  749.  samples, and one scanner driver of your choice (normally Hewlett-Packard). 
  750.  TWAIN enabling an existing imaging application should take less than a day and 
  751.  and only about two pages of C code.  The cost for the SDK is $695.00 USD. 
  752.  
  753.  The DDK allows a scanner manufacturer or third party developer to create fully 
  754.  reentrant, multitasking, multi- threaded Twain for OS/2 scanner drivers. The 
  755.  DDK contains carefully written and compilable base source code to which the 
  756.  DDK user writes only the specific interface code to his actual hardware 
  757.  device.  The DDK, priced at $4,995.00 USD, comes with a full years telephone 
  758.  support directly into Solution Technology's TWAIN engineering staff. 
  759.  
  760.  The optional annual software maintenance includes extended telephone support 
  761.  and kit updates for both the SDK and DDK are available at $105 USD/year (SDK) 
  762.  and $750 USD/year (DDK).  Each kit has a distribution license for the 
  763.  TWAIN.DLL.  Distribution licenses are available for the TWAININT.DLL, 
  764.  individual scanner drivers, or scanner driver packs at attractive rates. 
  765.  
  766.  TWAIN for OS/2 Scanner Drivers are being continually added to our inventory 
  767.  (see attached current scanner support list) and may be purchased individually 
  768.  or in packages of multiple scanner drivers.  Integrators and Developers can 
  769.  take advantage of our "Create-a-pak" licensing agreement to "roll- their-own" 
  770.  driver packages without incurring the costs of distributing scanner drivers 
  771.  they don't need.  Run-time licenses are based on volume and the type of 
  772.  scanner drivers required. 
  773.  
  774.  Please feel free to call if there are any questions. 
  775.  
  776.  TWAIN for OS/2 SDK 
  777.  
  778.  The Twain for OS/2 SDK is a developer's kit for TWAIN enabling any OS/2 
  779.  imagingapplication.  Our Twain package allows images to be efficiently 
  780.  captured in bi-level, gray scale, pallet color, or full 24 bit color without 
  781.  restrictionson image size.  In addition, Twain for OS/2 production scanners 
  782.  easily achieve scanning at or near their rated full speeds.  Compliance with 
  783.  the TWAIN standard ensures that any OS/2 Twain enabled application will 
  784.  operate with anyOS/2 Twain enabled scanner to acquire images. 
  785.  
  786.  SDK Features: 
  787.  
  788.      Full 32-bit multithreaded, multiprocess implementation 
  789.      Fully Twain Release 1.5 compliant 
  790.      Requires less than one page of user C code in existing imaging 
  791.       applications for Twain enablement 
  792.      OS/2 compliant applications will run with any OS/2 Twain compliant 
  793.       scanner or imaging device 
  794.      SDK Extended Support and SDK maintenance options available 
  795.      Includes distribution license for TWAIN.DLL 
  796.      Scanner driver runtime licenses available individually or in packages of 
  797.       multiple devices 
  798.      Nominal licensing fee to distribute the TWAININT.DLL (fast Twain enabler 
  799.       DLL) 
  800.  
  801.  Each SDK Includes: 
  802.  
  803.      TWAININT.DLL - Interface DLL to Twain Source Manager 
  804.      TWAIN.DLL - Twain Source Manager DLL 
  805.      One OS/2 Twain binary scanner driver of your choice (Hewlett-Packard SCSI 
  806.       driver default) 
  807.      OS/2 SDK Supplement to Twain Release 1.5 manual 
  808.      Sample OS/2 SDK source code for simple Twain enabled viewer 
  809.  
  810.  Requires: 
  811.  
  812.      OS/2 2.1, 2.11, Warp, or Warp Connect 
  813.      OS/2 Compatible supported scanner devices 
  814.      CSET/2 or CSET/2++ or equivalent tools 
  815.  
  816.  STI Supported Scanners: 
  817.  
  818.      Hewlett-Packard IIP, IIC, IICX, 3P, 3C, 3CX 
  819.      Logitech Scanman 256 
  820.      Bell & Howell 3338 
  821.      Epson 1200C, GT-9000 Series 
  822.      Fujitsu 3096, 3097, and ScanPartner 10 
  823.  
  824.  Under Development at STI: 
  825.  
  826.      Microtek IISP 
  827.      Mustek MFS-6000CX 
  828.      Others Please Call 
  829.  
  830.  TWAIN for OS/2 DDK 
  831.  
  832.  The Twain for OS/2 DDK is a developer's kit for imaging device manufacturers 
  833.  to develop a Twain for OS/2 device driver.  Our Twain DDK package allows the 
  834.  developer to create device drivers which efficiently capture images in 
  835.  bi-level, gray scale, pallet color, or full 24 bit color without restrictions 
  836.  on image size.  In addition, the DDK contains code which permits the developer 
  837.  to implement drivers which support high performance production scanners.  The 
  838.  structure of the DDK helps assure compliance with the TWAIN standard which 
  839.  ensures that your device driver will operate with any OS/2 Twain enabled 
  840.  application.  If you would rather have OS/2 experts develop your device 
  841.  driver, you can contract Solution Technology to develop it for you. 
  842.  
  843.  DDK Features: 
  844.  
  845.      Full 32-bit multi-threaded, multi-process implementation 
  846.      Fully Twain Release 1.5 compliant 
  847.      Typically takes two to four weeks to implement a Twain scanner device 
  848.       driver 
  849.      Manufacturer adds typically from 15 to 25 percent more code 
  850.      Multi-thread code for high-speed scanner management included 
  851.      All normal Twain messages already handled in supplied toolkit code 
  852.      OS/2 compliant applications will run with any OS/2 Twain compliant 
  853.       scanner or imaging device 
  854.      DDK Extended Support and DDK maintenance options available 
  855.      Distribute your scanner device driver royalty free 
  856.  
  857.  Each DDK Includes: 
  858.  
  859.      Twain for OS/2 SDK which includes: 
  860.         -  TWAIN.DLL - Twain Source Manager DLL 
  861.         -  TWAININT.DLL - Interface to Twain Source Manager 
  862.         -  OS2 SDK Supplement to Twain Release 1.5 manual 
  863.         -  Sample OS/2 SDK source code for simple Twain enabled viewer 
  864.         -  One OS/2 Twain binary scanner driver of your choice (Hewlett-Packard 
  865.            SCSI driver default) 
  866.         -  One OS/2 Twain source of a sample scanner driver; only need to 
  867.            implement manufacturer specific codes 
  868.      OS/2 DDK Supplement to Twain Release 1.5 manual 
  869.      OS/2 ASPI adapter driver example kit for SCSI scanners 
  870.      One year telephone support directly into Solution Technology's TWAIN 
  871.       engineering staff 
  872.  
  873.  Requires: 
  874.  
  875.      OS/2 2.1, 2.11, Warp, or Warp Connect 
  876.      OS/2 Kernel debugger strongly recommended 
  877.      OS/2 Compatible supported scanner devices 
  878.      CSET/2 or CSET/2++ or equivalent tools 
  879.  
  880.  Add your scanner to this growing Twain for OS/2 support list: 
  881.  
  882.      Hewlett-Packard IIP, IIC, IICX, 3P, 3C, 3CX 
  883.      Logitech Scanman 256 
  884.      Bell & Howell 3338 
  885.      Epson 1200C, GT-9000 Series 
  886.      Fujitsu 3096, 3097, and ScanPartner 10 
  887.  
  888.  Under Development at STI: 
  889.  
  890.      Microtek IISP 
  891.      Mustek MFS-6000CX 
  892.      Others Please Call 
  893.  
  894.   Solution Technology, Inc. - "We provide solutions..."
  895.   1101 South Rogers Circle, Suite 14
  896.   Boca Raton, FL 33487
  897.  
  898.   Phone: (407) 241-3210
  899.   Fax: (407) x997-6518
  900.   E-mail: solution@gate.net
  901.  
  902.  Twain for OS/2, Twain Source Manager, all libraries and DLLs are proprietary 
  903.  products of Solution Technology, Inc. 
  904.  
  905.  Twain for OS/2 is a trademark of Solution Technology, Inc. 
  906.  
  907.  OS/2 is a trademark of IBM Corporation 
  908.  
  909.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  910.  
  911.  
  912. ΓòÉΓòÉΓòÉ 4. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  913.  
  914. How Do I Get EDM/2? 
  915.  
  916. EDM/2 can be obtained in any of the following ways: 
  917.  
  918. On the Internet 
  919.  
  920.      All back issues are available via anonymous FTP from the following sites: 
  921.  
  922.         -  hobbes.nmsu.edu in the /os2/newsltr directory. 
  923.  
  924.         -  ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  925.  
  926.         -  generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  927.  
  928.      The EDM/2 mailing list.  Send an empty message to edm2- 
  929.       info@knex.mind.org to receive a file containing (among other things) 
  930.       instructions for subscribing to EDM/2.  This is a UUCP connection, so be 
  931.       patient please. 
  932.  
  933.      IBM's external gopher/WWW server in Almaden.  The address is 
  934.       index.almaden.ibm.com and it is in the "Non-IBM- Originated" submenu of 
  935.       the "OS/2 Information" menu; the URL is 
  936.       "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70". 
  937.  
  938.  On Compuserve 
  939.  
  940.      All back issues are available in the OS/2 Developers Forum 2. 
  941.  
  942.  IBM Internal 
  943.  
  944.      IBM's internal gopher/WWW server in Almaden.  The address is 
  945.       n6tfx.almaden.ibm.com and it is in the "Non-IBM- Originated Files" menu; 
  946.       the URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70". 
  947.  
  948.  On BBS's 
  949.  
  950.      From BBS's in Denmark, send email to Jesper Nielsen at 
  951.       afdata@pop02.ny.us.ibm.net for a location near you. 
  952.  
  953.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  954.  
  955.  
  956. ΓòÉΓòÉΓòÉ 5. C++ Compiler Review (Part 2) ΓòÉΓòÉΓòÉ
  957.  
  958. C++ Compiler Review (Part 2) 
  959.  
  960. Written by Gordon Zeglinski 
  961.  
  962. Introduction 
  963.  
  964. The second installment to our compiler review appears in this issue.  We will 
  965. look at Borland C++ version 2.0 for OS/2 and Metaware High C/C++ version 3.32. 
  966. In addition to featuring these two compilers, the results of a series of 
  967. benchmarks will be presented.  The benchmarks were cut down from the set listed 
  968. in the last issue due to time constraints. 
  969.  
  970. These two compilers are at opposite ends of the user spectrum.  Borland C++ is 
  971. a low cost quick compiler, with a good IDE.  Metaware is at the high end of the 
  972. cost spectrum, supports numerous target environments, and is really designed 
  973. for those seeking the ultimate performance. 
  974.  
  975. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  976.  
  977.  
  978. ΓòÉΓòÉΓòÉ 5.1. Borland C++ version 2.0 ΓòÉΓòÉΓòÉ
  979.  
  980. Borland C++ version 2.0 
  981.  
  982. The Borland package requires about 60 megs of HD space to install.  The package 
  983. includes PM and text mode compilers and debuggers.  The OS/2 2.1 toolkit is 
  984. also included.  The PM mode compiler is part of the IDE.  In addition to tools 
  985. to help convert Windows resources to OS/2 resources, there is an OS/2 version 
  986. of TASM.  (Personally, TASM is my favorite assembler.) Only OS/2 is supported 
  987. by this package, however; to do DOS and Windows applications the Windows 
  988. version must be purchased.  A nice feature is that OWL (Object Window Library) 
  989. is now supported under both PM and Windows. 
  990.  
  991. Compiler 
  992.  
  993. This is the fastest compiler evaluated.  It is significantly faster than Watcom 
  994. 10a, which is the second fastest compiler evaluated.  On the flip side the code 
  995. produced by Borland is slower than that of all the the compilers.  As far as 
  996. RAM requirements go, this system was easily able to handle them.  It supports 
  997. C++ exceptions, templates, run time type identification, and the new style 
  998. casts.  As can be expected, moving from the DOS/Windows version is fairly easy 
  999. especially if you use OWL, although the BGI functions are not included in the 
  1000. OS/2 version.  The CRTL is designed to work around the problem of OS/2 not 
  1001. unloading and loading DLLs in a guaranteed order (which does cause problems in 
  1002. CSet 2.1 under certain circumstances).  While on the topic of the CRTL, 
  1003. complete source code to the CRTL, OWL and class libraries is included on the CD 
  1004. version. 
  1005.  
  1006. Like VAC++, Borland had problems compiling one of the C++ test objects. 
  1007.  
  1008. Development Environment 
  1009.  
  1010. The PM IDE has a built in debugger and compiler.  It follows the same design as 
  1011. the Windows and DOS IDEs.  The built-in editor is one of the best I've used. 
  1012. Although the IDE is not as open or flexible as Workframe/2, it is very capable 
  1013. of handling complex projects.  One bug I noticed is that in the IDEs project 
  1014. "memory", it does not store the fully qualified path to the project file. 
  1015. Thus, unless the current working directory happens to be the same as the 
  1016. project file, the memory feature is useless. 
  1017.  
  1018. The IDE also contains a code browser.  With the browser, one can examine both C 
  1019. and C++ code.  Function chains can be followed.  In the case of C++, object 
  1020. hierarchies and objects can be explored.  The browser could use some threading 
  1021. on startup and there should be an easy way to "Backup".  Each time you open a 
  1022. new more detailed browser view, the previous view disappears.  It would be 
  1023. useful to be able to "backup" to the less detailed view. 
  1024.  
  1025. Borland is the only compiler package that ships with a decent resource editor. 
  1026. Borland's dialog editor is the best part of the resource package. The resource 
  1027. workshop is less featured than their windows counter part.  The editor may have 
  1028. problems on some systems working with icons, and bitmaps.  If the resource 
  1029. editor was as good as their Windows resource workshop, it alone would nearly 
  1030. justify buying this package.  Unfortunately it is almost identical to the 
  1031. version shipped in version 1.0. 
  1032.  
  1033. Debugger 
  1034.  
  1035. The most noticeable change from version 1.0 is the improved stability.  The 
  1036. debugger doesn't offer any PM-specific debugging aids.  However, the debugger 
  1037. has an appealing design and is easy to use.  Its a lot easier to view a pointer 
  1038. as an array in Borland's debugger than in C-Set++'s debugger.  It has no 
  1039. scripting capability, unfortunately. 
  1040.  
  1041. Documentation 
  1042.  
  1043. In keeping with Borland tradition, there's a lot of documentation.  The 
  1044. documentation is well written and useful to new and experienced programmers. 
  1045. The manuals themselves seem to be made of low grade paper and bindings.  The 
  1046. quality of the material is below that of the Metaware or Watcom manuals, but 
  1047. the ease of use exceeds that of the Watcom manuals.  The following manuals are 
  1048. included: 
  1049.  
  1050.      Borland C++ Library Reference 
  1051.      Borland C++ User's Guide 
  1052.      Borland C++ Programmer's Guide 
  1053.      Turbo Assembler Quick Reference Guide 
  1054.      Turbo Assembler User's Guide 
  1055.      Turbo Debugger User's Guide 
  1056.      Turbo Debugger GX User's Guide 
  1057.      Tools & Utilities Guide 
  1058.      Resource Workshop User's Guide 
  1059.      ObjectWindows Reference Guide 
  1060.      ObjectWindows Programmer's Guide 
  1061.      ObjectWindows Tutorial 
  1062.  
  1063.  Summary 
  1064.  
  1065.  Overall, the package shows great improvements in some areas and little 
  1066.  improvement in others.  In particular the lack of improvement to the resource 
  1067.  workshop is most annoying.  The compiler supports more C++ features than 
  1068.  either C-Set++ or Watcom and is extremely fast.  This makes it an ideal 
  1069.  compiler for new programmers.  At the same time, the PM version of OWL allows 
  1070.  programmers to create code that runs under both Windows (using the Windows 
  1071.  version of the product) and OS/2. 
  1072.  
  1073.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1074.  
  1075.  
  1076. ΓòÉΓòÉΓòÉ 5.2. Metaware High C/C++ version 3.32 ΓòÉΓòÉΓòÉ
  1077.  
  1078. Metaware High C/C++ version 3.32 
  1079.  
  1080. The Metaware package requires about 13 megs of HD space to install.  The 
  1081. package includes text mode debugger, the OS/2 2.1 toolkit, and Tools.h++ by 
  1082. Rogue Wave.  Installation was pretty simple.  Although the package only 
  1083. includes support for OS/2, Metaware has versions of the compiler available for 
  1084. DOS, Windows, and various flavors of unix. 
  1085.  
  1086. Compiler 
  1087.  
  1088. The compiler is slow but generates fast code.  The error messages generated by 
  1089. the compiler are very precise and make fixing compile time errors fairly easy. 
  1090. High C/C++ has the most complete C++ implementation of any of the reviewed 
  1091. compilers.  It supports templates, C++ exceptions, run time type 
  1092. identification, name spaces, new type casting methods, and C++ iterators.  In 
  1093. addition to having the most complete C++ implementation, Metaware was a pioneer 
  1094. in Direct To Som (DTS) technology and High C/C++ was the first OS/2 compiler to 
  1095. support DTS. 
  1096.  
  1097. High C/C++ has tighter C syntax rules than the other C compilers but it 
  1098. supports many nice extensions.  For instance, you can compile C code in 
  1099. "Incremental C++ mode".  This allows you to use C++ features in a C program 
  1100. without all the syntax rules of C++ being enforced.  Case statements can 
  1101. support ranges like, "case 'A'..'C':".  There are many more extensions. 
  1102.  
  1103. Virtually every aspect of the optimizer can be individually toggled on and off. 
  1104. The compiler has switches and #pragmas to configure just about everything. 
  1105. This is both good and bad.  It's good because it allows you to remove an 
  1106. optimization that may be causing a bug or affecting performance adversely or 
  1107. cause some other strange side effect.  It's bad because you can play with 
  1108. switches and pragmas for a long time if you get into it. 
  1109.  
  1110. Development Environment 
  1111.  
  1112. Support for IBM's Workframe/2 version 1.x is included.  No native IDE is 
  1113. provided. 
  1114.  
  1115. Debugger 
  1116.  
  1117. The debugger is useable although awkward in interactive mode.  It's essentially 
  1118. a command line debugger wrapped loosely with a menu system.  For instance, a 
  1119. local variable display can be accessed through a menu option. However, when the 
  1120. local variable view window is open, it's not possible to step the debugger. 
  1121.  
  1122. The powerful scripting language allows one to create a batch file for debugging 
  1123. an application.  Combine the powerful script support with the poor interactive 
  1124. support, one ends up with a debugger that is best suited for batch debugging. 
  1125.  
  1126. Documentation 
  1127.  
  1128. The documentation covers covers the various operating systems supported by the 
  1129. compiler.  This allows one to plan for cross platform support.  Even though 
  1130. multiple operating systems are included in the same manuals, they do not suffer 
  1131. a reduction in readability.  The indexes are organized well, making it easy to 
  1132. find information.  I find these manuals to be among the best I've ever used. 
  1133. The following manuals are included: 
  1134.  
  1135.      High C/C++ Language Reference 
  1136.      High C Library Reference 
  1137.      High C/C++ I/O Streams Library Reference 
  1138.      High C/C++ Programmer's Guide 
  1139.      High C/C++ DirectToSOM Developer's Guide 
  1140.      High C/C++ Debugger User's Guide and Reference 
  1141.      High C/C++ New Information 
  1142.      High C/C++ Installation Guide 
  1143.      High C/C++ Language Quick Reference Notes 
  1144.      High C/C++ I/O Streams Library Quick Reference Notes 
  1145.      Tools.h++ Introduction and Reference Manual 
  1146.  
  1147.  Summary 
  1148.  
  1149.  Although the compiler is slow, it produces fast code and good diagnostic 
  1150.  messages.  When it comes to C++ and DTS support, this compiler is the leader. 
  1151.  If you need an interactive debugger, though, you will probably have to find 
  1152.  one that supports Metaware.  In addition, you will have to get PM specific 
  1153.  debugging aids from a DevCon CD or someplace else. 
  1154.  
  1155.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1156.  
  1157.  
  1158. ΓòÉΓòÉΓòÉ 5.3. Benchmarks ΓòÉΓòÉΓòÉ
  1159.  
  1160. Benchmarks 
  1161.  
  1162. We finally get to the benchmarks.  As I mentioned previously, the benchmarks 
  1163. were scaled down a bit.  The following table shows the results of the C 
  1164. benchmarks: 
  1165.  
  1166. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1167. ΓöéCompiler  ΓöéBsort     ΓöéSieve     ΓöéDhrystone 21   ΓöéWhetstone (S)  ΓöéWhetstone (D)  Γöé
  1168. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1169. ΓöéMetaware  Γöé2.468     Γöé4.218     Γöé62500.0        Γöé142857         Γöé111111         Γöé
  1170. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1171. ΓöéVAC++     Γöé2.219     Γöé3.750     Γöé58139.5        Γöé34482          Γöé34482          Γöé
  1172. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1173. ΓöéWatcom    Γöé1.970     Γöé1.090     Γöé65789.5        Γöé111111         Γöé76923          Γöé
  1174. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1175. ΓöéBorland   Γöé2.406     Γöé6.062     Γöé32467.5        Γöé17241          Γöé17241          Γöé
  1176. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1177.  
  1178. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1179. ΓöéCompiler  ΓöéRolled Linpack (S)       ΓöéRolled Linpack (D)       ΓöéUnrolled Linpack (S)     ΓöéUnrolled Linpack (D)     Γöé
  1180. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1181. ΓöéMetaware  Γöé3135                     Γöé2194                     Γöé3135                     Γöé2312                     Γöé
  1182. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1183. ΓöéVAC++     Γöé2928                     Γöé1996                     Γöé2928                     Γöé2090                     Γöé
  1184. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1185. ΓöéWatcom    Γöé2922                     Γöé1990                     Γöé3121                     Γöé2328                     Γöé
  1186. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1187. ΓöéBorland   Γöé2444                     Γöé1758                     Γöé2586                     Γöé1829                     Γöé
  1188. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1189.  
  1190. The units for the C benchmarks are as follows.  Bsort and Sieve are in seconds 
  1191. (the smaller the number the better).  Dryhstone 21 is in Dhrystones/sec.  The 
  1192. two whetstone tests are in KWhets/sec.  All the Linpack tests are in Kflops. 
  1193. With the exception of the first two benchmarks, larger numbers are better. 
  1194.  
  1195. The following table show the results of the C++ benchmark. 
  1196.  
  1197. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1198. ΓöéCompiler  ΓöéTest 1    ΓöéTest 2    ΓöéTest 3    ΓöéTest 4    ΓöéTest 5    Γöé
  1199. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1200. ΓöéMetaware  Γöé3.187     Γöé8.531     Γöé2.938     Γöé33.406    Γöé10.344    Γöé
  1201. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1202. ΓöéVAC++     Γöé2.187     ΓöéNA        Γöé2.282     Γöé460.156   ΓöéNA        Γöé
  1203. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1204. ΓöéWatcom    Γöé3.090     Γöé18.720    Γöé4.910     Γöé93.400    Γöé20.970    Γöé
  1205. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1206. ΓöéBorland   Γöé3.406     ΓöéNA        Γöé3.032     Γöé825.344   ΓöéNA        Γöé
  1207. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1208.  
  1209. Test 1 simply tests the construction and destruction of an object including a 
  1210. call to its virtual function. 
  1211.  
  1212. Test 2 is like test 1 except a more complex object is used. 
  1213.  
  1214. Test 3 is similar to test 1 except that the object is created/destroyed from 
  1215. within a try/catch block. 
  1216.  
  1217. Test 4 is like test 3 except that an exception is actually thrown and caught. 
  1218.  
  1219. Test 5 assigns the complex object to another object.  The same complex object 
  1220. that was used in test 2 is used here. 
  1221.  
  1222. Test 3 uses 1 less function calls than test 1. In theory, it should use up less 
  1223. time than test 1 unless the amount of time used to setup the try/catch block 
  1224. exceeds that of a function call.  In both the Metaware and Borland test 
  1225. results, test 3 was faster than test 1. The following table shows the 
  1226. compilation time and executable size for the C++ bench mark program. 
  1227.  
  1228. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1229. ΓöéCompiler  ΓöéCompile+Link Times       ΓöéExecutable Speeds        ΓöéEXE size (bytes)         Γöé
  1230. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1231. ΓöéMetaware  Γöé629.47                   Γöé2.37                     Γöé128579                   Γöé
  1232. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1233. ΓöéVAC++     Γöé189.10                   Γöé2.50                     Γöé136755                   Γöé
  1234. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1235. ΓöéWatcom    Γöé232.22                   Γöé2.07                     Γöé96027                    Γöé
  1236. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1237. ΓöéBorland   Γöé168.53                   Γöé2.40                     Γöé140339                   Γöé
  1238. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1239.  
  1240. The unzip test compares the compilation time, executable speed, and executable 
  1241. size for Info unzip version 5.12.  The following table shows the results of the 
  1242. unzip test. 
  1243.  
  1244. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1245. ΓöéCompiler  ΓöéCompile+Link Times       ΓöéEXE Size (bytes)         Γöé
  1246. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1247. ΓöéMetaware  Γöé59.19                    Γöé80400                    Γöé
  1248. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1249. ΓöéVAC++     Γöé35.35                    Γöé39936                    Γöé
  1250. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1251. ΓöéWatcom    Γöé84.63                    Γöé65898                    Γöé
  1252. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1253. ΓöéBorland   Γöé14.22                    Γöé41489                    Γöé
  1254. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1255.  
  1256. Notes 
  1257.  
  1258. The command line used to test executable speed was unzip -t unzip512.zip >NUL. 
  1259.  
  1260. Although VAC++ compiled unzip faster than Watcom, this is usually not the case. 
  1261. VAC++ takes twice as long to compile the AdeptXBBS source code. Automatic 
  1262. function inlining had to be turned off in VAC++ because the resulting EXE 
  1263. falsely reported error in a good zip file.  Metaware had inlining turned on. 
  1264.  
  1265. Included Files 
  1266.  
  1267. The source code to the C and C++ benchmark programs is included, along with the 
  1268. .cmd files used to compile the executables.  The raw output from the benchmarks 
  1269. is also included.  The executables are not included to keep the size of the 
  1270. distribution down. 
  1271.  
  1272. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1273.  
  1274.  
  1275. ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
  1276.  
  1277. Summary 
  1278.  
  1279. So you're probably wondering which compiler is the best compiler for OS/2 
  1280. programming.  When I started this series, I thought I'd be able to say 
  1281. definitively that compiler XXX is the best without a doubt.  Unfortunately it's 
  1282. not that easy because no single compiler is the best.  Below I'll try to give 
  1283. some guidelines on what I think each compiler is best suited for. 
  1284.  
  1285. The Metaware compiler has the best OOP support around.  It was the first 
  1286. compiler to support direct to SOM and has the most complete C++ implementation 
  1287. of the reviewed compilers.  Its code optimizer is one of the best so if code 
  1288. speed is important then this compiler is worth considering.  It's definitely 
  1289. not for the hobbyist, however. 
  1290.  
  1291. The Watcom compiler can generate executable for almost every PC operating 
  1292. system.  This makes it the choice for cross platform development.  In addition, 
  1293. Watcom usually makes the smallest executables.  Unfortunately the compatibility 
  1294. problems with Warp make version 10a less than perfect, though version 10.5 
  1295. should fix these problems.  Watcom is a great "mid level" package - it 
  1296. generates fast code with the smallest executable size.  Watcom is such a 
  1297. versatile package it's great for the novice programmer as well as the 
  1298. professional. 
  1299.  
  1300. Visual Age C++ has the highest system requirements.  Although at present it 
  1301. needs a few CSDs, once these are released, it should be the ideal compiler for 
  1302. people needing to make large cross platform projects.  Although the package 
  1303. only supports OS/2, it is available on several other hardware platforms and 
  1304. operating systems.  The "Open Class" library abstracts windowing, threading and 
  1305. more from the application.  This allows a high degree of code reusability when 
  1306. moving the application to another environment supported by VAC++.  This package 
  1307. is definitely not designed for the hobbyist.  Professional programmers with 
  1308. some serious hardware that want to do visual programming should consider this 
  1309. package. 
  1310.  
  1311. Borland C++ is the quickest compiler of the ones we have looked at.  In 
  1312. general, its optimizer isn't as good as the other 3 compilers.  Through OWL, 
  1313. one can create PM and Windows programs from the same source without too much 
  1314. difficulty.  (Of course to do Windows programming, you have to purchase the 
  1315. Windows version of the compiler.)  The Windows version has a lot more polish 
  1316. than the OS/2 version.  Borland is a good choice for a beginner programmer and 
  1317. those who are familiar with OWL. 
  1318.  
  1319. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1320.  
  1321.  
  1322. ΓòÉΓòÉΓòÉ 6. Easy Buttonbars ΓòÉΓòÉΓòÉ
  1323.  
  1324. Easy Buttonbars 
  1325.  
  1326. Written by Eric Slaats 
  1327.  
  1328. Introduction 
  1329.  
  1330. When I started programming PM applications I was really amazed that simple, 
  1331. common things that most application feature like buttonbars, multi windowing 
  1332. (tile, cascade etc.)  weren't standard features.  On my first attempt to build 
  1333. an application, I wanted to include a buttonbar so I started looking for an API 
  1334. call that would place all the buttons for me in the right place.  There isn't 
  1335. such a call!  The lack of this call made me construct a method like Marc and I 
  1336. described in "Building Custom Controls" (see EDM/2 3-4).  The method described 
  1337. in that article is complete and does everything it should do. However, I wasn't 
  1338. satisfied with the amount of code it took when writing another (very small) 
  1339. application.  So I started to experiment with the menu styles and found a very 
  1340. simple way to implement a buttonbar. 
  1341.  
  1342. In this (short) article I'll describe this very simple approach to build a 
  1343. buttonbar.  It functions very well, but it also has some drawbacks (see the 
  1344. section Concluding Notes).  If you're willing to accept this, you'll be 
  1345. rewarded with a toolbar which is very very easy to implement. 
  1346.  
  1347. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1348.  
  1349.  
  1350. ΓòÉΓòÉΓòÉ 6.1. Bitmap Buttons In A Menu ΓòÉΓòÉΓòÉ
  1351.  
  1352. Bitmap Buttons In A Menu 
  1353.  
  1354. In the introduction I stated that there isn't a API call to build a buttonbar. 
  1355. In fact this isn't true.  We can build a menu filled completely with buttons 
  1356. containing a bitmap.  So, in fact, OS/2 has a method to build a buttonbar! 
  1357. (This approach is already been handled in "Building Custom Controls" in EDM/2 
  1358. 3-4.) 
  1359.  
  1360. To use bitmaps in a menu, the bitmaps should be known in the .RC file.  To 
  1361. accomplish this we need to do two things.  First we need to create identifiers 
  1362. for all the the bitmaps we want to use.  These are usually kept in the header 
  1363. file. 
  1364.  
  1365. // Bitmap identifiers
  1366. #define ONE    101
  1367. #define TWO    102
  1368. #define THREE  103
  1369. #define FOUR   104
  1370. #define FIVE   105
  1371.  
  1372. Figure 1) Bitmap identifiers 
  1373.  
  1374. These declarations are used in the RC file to associate the bitmaps with an 
  1375. identifier. 
  1376.  
  1377. // Bitmap declaration
  1378. BITMAP ONE     "ONE.BMP"
  1379. BITMAP TWO     "TWO.BMP"
  1380. BITMAP THREE   "THREE.BMP"
  1381. BITMAP FOUR    "FOUR.BMP"
  1382. BITMAP FIVE    "FIVE.BMP"
  1383.  
  1384. Figure 2) Bitmap filename declaration 
  1385.  
  1386. The next step in creating a menu with bitmaps is building the actual menu. The 
  1387. following lines in the .RC file describe the buttonbar menu. 
  1388.  
  1389. // Menu declaration
  1390. MENU TOOLMENU
  1391. BEGIN
  1392. MENUITEM   "#101",  IDM_ONE,  MIS_BITMAP  MENUITEM   "#102",
  1393. IDM_TWO,  MIS_BITMAP MENUITEM "#103", IDM_THREE,  MIS_BITMAP
  1394. MENUITEM   "#104",   IDM_FOUR,   MIS_BITMAP   MENUITEM   "",
  1395. MIS_SEPARATOR
  1396. MENUITEM "#105", IDM_FIVE, MIS_BITMAP END
  1397.  
  1398. Figure 3) Menu template 
  1399.  
  1400. The menustyle for each of the buttons is MIS_BITMAP.  This means the menuitem 
  1401. will display as a bitmap and the RC compiler expects the identifiers of the 
  1402. bitmaps in the textarea of the menuitems.  We'll put the identifier of the 
  1403. bitmap preceded by a `#' in the text area. 
  1404.  
  1405. Besides the declaration of the menuitems a MIS_SEPARATOR is included.  This 
  1406. line in the RC file will put a blank between the buttons FOUR and FIVE.  This 
  1407. way we have a method to separate groups of buttons. 
  1408.  
  1409. If a window is built using the menu described above, we'll get a window which 
  1410. will look like this: 
  1411.  
  1412. Figure 4) Window with a simple buttonbar 
  1413.  
  1414. In this example button 32X32 bitmaps are used.  These bitmaps are shaped as a 
  1415. button.  Of course any bitmap can be used.  The bitmaps used in this example 
  1416. can be found in the toolbar2.zip file.  [Editor's note - Eric forgot to send 
  1417. this file with the article.  It will be placed on the EDM/2 ftp site as soon as 
  1418. possible.] 
  1419.  
  1420. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1421.  
  1422.  
  1423. ΓòÉΓòÉΓòÉ 6.2. Adding 'Normal' Menu Items ΓòÉΓòÉΓòÉ
  1424.  
  1425. Adding 'Normal' Menu Items 
  1426.  
  1427. Well I promised a simple buttonbar.  The 'trick' is indeed very simple.  We add 
  1428. the normal menuitems to the menu defined in the previous section.  The thing to 
  1429. do is to give the 'normal' menu items the same identifier as the corresponding 
  1430. button.  (It isn't forbidden to have more than one item with the same 
  1431. identifier in one menu!)  This way we're sure the button and the menuitem 
  1432. trigger the same case item in the window procedure. 
  1433.  
  1434. If we leave the menu like this, the buttons and the menuitems are displayed in 
  1435. one row (given a large enough window).  If we want a buttonbar, we want it to 
  1436. be displayed underneath the normal menu items.  This effect can be accomplished 
  1437. to ad the MIS_BREAK stye to the first menuitem that has to be displayed on the 
  1438. second row.  The menu code in the RC file should look something like this: 
  1439.  
  1440. // Menu declaration
  1441. MENU TOOLMENU
  1442. BEGIN
  1443.      MENUITEM "~One", IDM_ONE
  1444.      MENUITEM "~Two", IDM_TWO
  1445.      MENUITEM "Th~ree", IDM_THREE MENUITEM "~Four", IDM_FOUR
  1446. MENUITEM "F~ive", IDM_FIVE
  1447.        MENUITEM  "#101",  IDM_ONE,  MIS_BITMAP  |  MIS_BREAK
  1448. MENUITEM "#102", IDM_TWO, MIS_BITMAP
  1449.      MENUITEM "#103", IDM_THREE, MIS_BITMAP MENUITEM "#104",
  1450. IDM_FOUR, MIS_BITMAP MENUITEM "", MIS_SEPARATOR
  1451.      MENUITEM "#105", IDM_FIVE, MIS_BITMAP
  1452. END
  1453.  
  1454. Figure 5) New menu template 
  1455.  
  1456. The MIS_BREAK style is normally used to build a submenu with two or more 
  1457. columns.  Using it like this we create a menu with two rows, thus separating 
  1458. the menu items from the button items.  Used in a window this should look 
  1459. something like this: 
  1460.  
  1461. Figure 6) New buttonbar appearance 
  1462.  
  1463. A complete working example can be found in the toolbar2.zip file. 
  1464.  
  1465. Note:  The menu control also has a style called MIS_BREAKSEPARATOR.  Using this 
  1466. style, the rows or columns separated by this style should be separated by a 
  1467. line.  I found that this worked perfectly with columns, but it didn't work with 
  1468. rows!  Maybe this is a bug, maybe my RC compiler is buggy?  Who knows? 
  1469.  
  1470. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1471.  
  1472.  
  1473. ΓòÉΓòÉΓòÉ 6.3. Concluding Notes ΓòÉΓòÉΓòÉ
  1474.  
  1475. Concluding Notes 
  1476.  
  1477. That was simple enough, but what are the drawbacks? 
  1478.  
  1479.      There isn't a line drawn between the buttonbar and the menubar.  Of 
  1480.       course this is a cosmetic effect, but I think it should be there. 
  1481.       MIS_BREAKSEPARATOR should work, but it doesn't.  I haven't fixed this 
  1482.       yet, but it should be possible with an owner drawn menuitem 
  1483.       (MIS_OWNERDRAWN). 
  1484.  
  1485.      This is just one menu.  That means it can't be split (buttons at the 
  1486.       bottom or side of the frame window, normal menu on top). 
  1487.  
  1488.      This also means the buttonbar and the normal menu can't be given 
  1489.       different colors. 
  1490.  
  1491.      Adding two toolbars, one on top, one at the bottom or side of the window 
  1492.       is impossible 
  1493.  
  1494.  Of course, this method hasn't the flexibility of a toolbar as it was described 
  1495.  in `Building Custom Controls,' let alone the flexibility of a (great) package 
  1496.  like UCMENU (see OS/2 Developer in the January/February 1995 issue).  But if 
  1497.  you can live with these drawbacks there are a number of pro's. 
  1498.  
  1499.      It's very simple 
  1500.  
  1501.      No extra programming needed, everything can be done with a resource 
  1502.       editor. 
  1503.  
  1504.      No subclassing required 
  1505.  
  1506.  A working example of a buttonbar created with this method is found in the file 
  1507.  toolbar2.zip.  This example is created and compiled with Borland C++ 2.0. 
  1508.  
  1509.  Feel free to use the code any way you like and send me your comments. 
  1510.  
  1511.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1512.  
  1513.  
  1514. ΓòÉΓòÉΓòÉ 7. Gearing Up For Games (Part 3) ΓòÉΓòÉΓòÉ
  1515.  
  1516. Gearing Up For Games (Part 3) 
  1517.  
  1518. Written by Michael T Duffy 
  1519.  
  1520. Introduction 
  1521.  
  1522. Welcome to the third installment of Gearing Up For Games.  The past couple of 
  1523. months have been really busy for me, and in August I took a two week trip to 
  1524. Japan that took me completely away from the computer.  Add to this the fact 
  1525. that I'm trying desperately to get my own game out before the end of the year, 
  1526. and you begin to see why I didn't get a chance to finish this article. 
  1527.  
  1528. I had planned on covering threads and semaphores, and basic sprites in this 
  1529. article.  It turns out that I have only had time to write about threads and 
  1530. semaphores.  However I wrote the code for the article before I started the 
  1531. text, so I finished all of the basic sprite code.  Rather than pull the sprite 
  1532. code out, I have left it in.  For those of you already familiar with sprites, 
  1533. you should be able to follow the code fairly easily.  The next to last section 
  1534. of this article briefly describes how I approached sprites, though it is not 
  1535. meant to be an in-depth explanation.  It will have to suffice for now. 
  1536.  
  1537. Also, I should point out that my discussion of threads and semaphores is 
  1538. oriented towards games, and does not cover all aspects of threads or 
  1539. semaphores.  A complete discussion is beyond the scope of this article, and I 
  1540. would suggest that you look into the reference documentation in the OS/2 
  1541. toolkit (namely Control Program Guide and Reference) as well as a good book or 
  1542. two on OS/2 programming.  I have found both Petzold's OS/2 Presentation Manager 
  1543. Programming (pub. Ziff- Davis Press) and Real World Programming for OS/2 2.11 
  1544. from SAMS Publishing to be useful references.  Each book covers some material 
  1545. that the other doesn't, so it may be a good idea to look at more than one 
  1546. explanation.  The material presented in this article should be enough to give 
  1547. you a basic understanding of threads and along with the accompanying sample 
  1548. code, you should be able to use threads and semaphores in your own game 
  1549. programs. 
  1550.  
  1551. Enough for excuses...time to get to the meat of the matter! 
  1552.  
  1553. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1554.  
  1555.  
  1556. ΓòÉΓòÉΓòÉ 7.1. Threads ΓòÉΓòÉΓòÉ
  1557.  
  1558. Threads 
  1559.  
  1560. One of the advantages of an operating system like OS/2 is that the programmer 
  1561. has available to him or her a multitasking environment.  This not only means 
  1562. that more than one program can be running concurrently, but also that different 
  1563. parts of the same program can execute concurrenly.  In DOS, programmers did not 
  1564. have multitasking and instead relied on interrupt handlers and reprogramming 
  1565. the internal timer chip in order to achieve this, e.g. reading the keyboard or 
  1566. joystick while blitting to the screen.  This is no longer necessary in OS/2, 
  1567. and part of the reason is because of threads. 
  1568.  
  1569. What is a thread?  A thread is a separate unit of execution within a program. 
  1570. Each thread has its own set of CPU register variables and its own stack.  For 
  1571. the beginner, register variables are the variables used inside of the CPU to 
  1572. perform calculations and keep track of where the program is currently 
  1573. executing.  The stack is where local variables are allocated and deallocated 
  1574. from when a new routine is entered.  Threads are owned by a process, where a 
  1575. process is usually the program that you are running. 
  1576.  
  1577. Multitasking is handled by the CPU, with the operating system telling the CPU 
  1578. how much time to give each thread.  It basically works like this: the CPU 
  1579. executes a thread for a given amount of time, stopping the thread after that 
  1580. time has elapsed.  The CPU stops the thread dead in its tracks, even if it is 
  1581. in the middle of executing a single line of C code, like usVariable1 = 
  1582. usVariable2.  All of the variables in the CPU registers are stored.  The OS 
  1583. then instructs the CPU which thread to run next, and the CPU loads its 
  1584. registers with the saved registers of the next thread, then executes that 
  1585. thread for a given amount of time, and so on.  An operating system like OS/2 
  1586. can determine how much CPU time a thread needs, and adjust the amount of time 
  1587. it gives a thread for its next execution.  The OS can also suspend a thread if 
  1588. the CPU is needed elsewhere, such as reading keyboard, COM port, or disk drive 
  1589. data.  This is equal to the interrupts of the days of DOS. 
  1590.  
  1591. As a result, you never know when control will be given to or taken from your 
  1592. thread.  You can indirectly affect how much time your thread is given by 
  1593. setting the priority level of the thread.  A priority level basically tells the 
  1594. CPU how important your thread is compared to other threads.  Threads that have 
  1595. a more important priority level are serviced before threads of lower priority. 
  1596. Threads of the same priority level are serviced in a round-robin fashion.  For 
  1597. example, let's say you have two threads of the priority, A and B, and one 
  1598. thread of a lower priority, C. Depending on the load level of the machine and 
  1599. other settings, these three threads might gain control in the order:  A B A B C 
  1600. A B A B A B A B C A B C A B C. Since A and B are of the same priority, they 
  1601. will be serviced equally.  Thread C will be serviced when A and B have been 
  1602. handled, and there is CPU time left over. 
  1603.  
  1604. As mentioned before OS/2 can adjust on the fly how much time each thread gets 
  1605. before the CPU stops it.  How does OS/2 determine how much time a thread uses? 
  1606. A thread can signal that it has used enough CPU time for now in two ways.  One, 
  1607. if you have a message queue then OS/2 knows when you're done processing because 
  1608. your message handling routine returns to the operating system once it has 
  1609. handled the message.  The second way is that threads can be suspended, resumed, 
  1610. or paused (with DosSleep()).  This will be discussed shortly. 
  1611.  
  1612. How are threads useful, and when do you use one? 
  1613.  
  1614. Threads are needed when you must do two or more things at the same time. An 
  1615. important thing to remember about threads however, is that on Intel based 
  1616. machines, two threads don't really execute at the same time.  The CPU runs one 
  1617. thread for a short time, switches to other threads, switches back to the first 
  1618. thread and so on.  Even on machines with SMP (Symmetrical Multi-Processors) 
  1619. often all of the threads of a given process are run on a single CPU.  A CPU can 
  1620. only execute a certain number of instructions per second, and all threads take 
  1621. up a share of those instructions.  It also takes time to switch from one thread 
  1622. to another, even though this amount of time is very, very short overall. 
  1623.  
  1624. Threads are therefore useful when you need to to several tasks at basically the 
  1625. same time, and you don't want to have to worry about giving each task its share 
  1626. of the CPU.  Instead, OS/2 will handle the thread management.  Good examples of 
  1627. threads are the thread that handles the main message queue, a thread that blits 
  1628. images to the screen, a thread that loads/saves/sends/receives data in the 
  1629. background, a thread that mixes sound, and perhaps a thread that handles the 
  1630. artificial intelligence (AI) of the other opponents in a game.  In your games 
  1631. you will always want to have at least two threads:  one to handle the main 
  1632. message queue, and one to handle the game mechanics.  The reason for this is 
  1633. that you should always spend a little time as possible in the message queue 
  1634. routine, otherwise you risk slowing down overall system performance.  One of 
  1635. the flaws of OS/2 is that it has a single system message queue.  Since the OS 
  1636. can't send out other messages until the message it just sent is processed, a 
  1637. greedy program that uses a lot of time between when it is sent a message and 
  1638. when it returns to the OS holds up other messages meant both for itself and for 
  1639. other programs. If the processing of a message will take a long time, it is 
  1640. better to instruct a second thread to handle the processing and then return to 
  1641. the OS.  This way the second thread can perform the processing while the OS 
  1642. continues to send out other messages. 
  1643.  
  1644. Threads are not very useful when you have a certain number of things that must 
  1645. be done in a certain order.  For example, in an action game you may have 
  1646. several tasks to complete in a certain time frame, and one must follow the 
  1647. other.  Every frame of a shooting game, you must read the joystick or keyboard, 
  1648. update the player's position, call the enemy AI routines and update their 
  1649. positions, move all missiles and bullets, and then draw the new graphics with 
  1650. the new positions to the display.  Even though you could theoretically 
  1651. calculate player movement and enemy AI at the same time, the player only sees 
  1652. the finished screen and everything else must be completed before that screen is 
  1653. rendered.  No matter how you arrange the above tasks, together all of the above 
  1654. tasks will require the same amount of CPU time before the screen can be 
  1655. blitted.  Placing each task in a separate thread would not speed things up, and 
  1656. in fact things would slow down because you will have to synchronize the 
  1657. threads' access to variables, and the overhead of switching threads itself will 
  1658. slow things down some.  The solution to the above problem is to place all of 
  1659. the tasks in the same thread. 
  1660.  
  1661. Other games can have different tasks running at the same time.  Consider a 
  1662. simulation or an adventure game.  These kind of games can have complex AI for 
  1663. the computer opponents, and the calculations for the AI take a long time. 
  1664. However, the player is not continually giving input and the opponents are not 
  1665. continually moving like in a fast paced action game.  The player might be 
  1666. studying graphics or maps, or even reading text while not inputting requests 
  1667. for new actions.  Rather than having the computer wait for the player to make a 
  1668. move before deciding how the computer opponents would move (as a DOS game would 
  1669. do), the computer can decide it's next move while the player is involved with 
  1670. non-intensive CPU activities.  If the computer does not finish a task before 
  1671. the player makes a move, then it can continue to process until it does make a 
  1672. decision.  Depending on the type of game, this would mean either stopping the 
  1673. game until the decision were made, or continuing with the previous action this 
  1674. turn until a new action is decided upon. 
  1675.  
  1676. Types of Threads 
  1677.  
  1678. There are two basic types of threads:  message queue and non- message queue. 
  1679. The type is determined obviously enough based upon whether or not that thread 
  1680. has created a message queue.  The type of thread you use will depend on your 
  1681. purpose.  Aside from having a message queue and a message queue handle, message 
  1682. queue threads differ from non-message queue threads in a few significant ways. 
  1683. Non-message queue threads cannot do the following: create windows, contain 
  1684. window procedures, send messages to window procedures with WinSendMsg() 
  1685. (although they can call WinPostMsg()), or call functions that cause messages to 
  1686. be sent to window procedures.  On the other hand, message queue threads cannot 
  1687. be suspended or blocked, or else they will hold up the rest of the operating 
  1688. system.  Also, it is important to note that you cannot use the message queue 
  1689. handle of another thread to call windowing procedures.  The strengths and 
  1690. weaknesses of each type should be weighed carefully when organizing your 
  1691. program. 
  1692.  
  1693. Using Threads 
  1694.  
  1695. Threads can be created either through the functions in a standard library, such 
  1696. as C/C++'s _beginthread() function, or through the OS/2 API. We will be using 
  1697. the latter approach since the OS/2 API allows more control over threads than 
  1698. the former approach.  I suggest that you obtain a copy of IBM's Control Program 
  1699. Guide and Reference for a complete reference to the thread and semaphore API. 
  1700.  
  1701. Note that when you use threads, you must compile with the switch that tells the 
  1702. compiler that you are working with a multithreaded program.  This switch tells 
  1703. the compiler to use a special version of the standard libraries that are 
  1704. "multithread-safe".  If two theads call the same or related functions in the 
  1705. standard C or C++ library at the same time, then there could be problems if 
  1706. this flag is not specified.  With the Watcom C/C++ compiler, the flag is -bm. 
  1707.  
  1708. To create a thread we call DosCreateThread().  We tell this function what 
  1709. routine the thread is to run and give a single parameter to be passed to that 
  1710. routine, tell it what the stack size of the new thread is to be and whether or 
  1711. not to commit the pages of the stack, and whether the thread it to be executed 
  1712. immediately or created in a suspended state. 
  1713.  
  1714. Once a thread is created, you should set its priority status with 
  1715. DosSetPriority().  You will have to experiment to find out what priority levels 
  1716. to use for each of your threads.  It is a good idea to have your message queue 
  1717. to be at a higher priority than your other threads so that the entire system 
  1718. will stay responsive. 
  1719.  
  1720. A thread ends itself by either by returning from initial thread function, or 
  1721. calling DosExit().  A thread may kill another thread by calling 
  1722. DosKillThread(), though it is often a good idea to signal a thread that it 
  1723. should kill itself so that it may shut down what it is doing before it 
  1724. terminates. 
  1725.  
  1726. Threads can also be temporarily stopped and restarted with the functions 
  1727. DosSuspendThread() and DosResumeThread().  While a thread is suspended, it does 
  1728. not take up any CPU time; it is simply not called.  When a message queue thread 
  1729. returns to the OS/2 kernel and there are no messages for it, the OS/2 suspends 
  1730. the thread until new messages are available.  Note that threads obviously 
  1731. cannot resume themselves since they are not running, though they can suspend 
  1732. themselves and other threads.  If a thread is created in a suspended state, you 
  1733. must call DosResumeThread() to begin its execution. 
  1734.  
  1735. Another way to temporarily suspend a thread is to call DosSleep(). This 
  1736. function takes a single parameter that tells the system how many milliseconds 
  1737. the thread should be suspended before it is resumed.  Note that this can not be 
  1738. used for exact timing purposes.  As soon as the time runs out, the thread that 
  1739. called DosSleep() will be considered again for CPU time slices, but other 
  1740. threads may execute before the recently resumed thread gets it's turn, 
  1741. especially if the other threads have a higher priority.  Calling DosSleep(0) 
  1742. causes the thread to release the remainder of it's CPU time for the current 
  1743. time slice back to OS/2 so that it can be used elsewhere.  This should be used 
  1744. in non-message queue threads where you don't want to hog CPU time and you don't 
  1745. have anything special to do.  It is especially useful at the bottom of a loop 
  1746. where you have just finished a task and you don't need to start the next task 
  1747. immediately.  This is not needed if you suspend the thread through other means. 
  1748.  
  1749. Finally, a thread can suspend itself until another thread has finished 
  1750. executing.  When DosWaitThread() is called, a flag is passed that specifies 
  1751. whether the function should wait for end of execution or not.  If DCWW_NOWAIT 
  1752. is specified, the function returns immediately and the error status tells 
  1753. whether or not the specified thread is still running.  If DCWW_WAIT is 
  1754. specified, then the function does not return until the specified thread 
  1755. terminates.  DosWaitThread() is useful when thread A wants to terminate thread 
  1756. B. Thread A signals thread B that it should terminate.  Thread A then calls 
  1757. DosWaitThread() with the wait flag specified.  Thread B receives the shutdown 
  1758. signal, cleans up what it needs to, and the exits gracefully.  As soon as 
  1759. thread B exits, DosWaitThread() returns and thread A can continue about its 
  1760. business. 
  1761.  
  1762. As far as the creating, executing, suspending, and resuming the execution of 
  1763. threads, that's all there is too it.  To communicate amongst different threads 
  1764. and to coordinate their use of global variables and memory, you will have to 
  1765. rely on semaphores. 
  1766.  
  1767. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  1768.  
  1769.  
  1770. ΓòÉΓòÉΓòÉ 7.2. Semaphores ΓòÉΓòÉΓòÉ
  1771.  
  1772. Semaphores 
  1773.  
  1774. A semaphore is like a traffic cop that keeps threads from crashing into each 
  1775. other.  They are needed because when the CPU switches from one thread to 
  1776. another, it may interrupt it anywhere.  For example, Thread A might be in the 
  1777. middle of updating a structure.  It gets halfway through the update, and then 
  1778. it is interrupted by the CPU and thread B gets control.  Thread B tries to use 
  1779. the information in the structure, but only half of it is correct.  Imagine if 
  1780. the structure contained a forward and backward linked list, and only one of the 
  1781. two pointers were updated.  Behavior of the program would be unpredictable and 
  1782. buggy.  It gets even worse.  Actions we consider atomic in C may actually be 
  1783. compiled down into several assembly language instructions.  Consider the 
  1784. expression ++usVar1; The compiler might break it down like: 
  1785.  
  1786. mov  eax, [usVar1]  ;eax = 0, usVar1 == 0
  1787. inc  eax            ;eax = 1, usVar1 == 0
  1788. mov  [usVar1], eax  ;eax == 1, usVar1 = 1
  1789.  
  1790. Figure 1) Assembler for ++usVar1 
  1791.  
  1792. What happens if Thread A is interrupted by Thread B during the middle of the 
  1793. command, and thread B tries something simple like incrementing usVar1. Remember 
  1794. that each thread has it's own set of CPU register variables. 
  1795.  
  1796. A - mov   eax, [usVar1]  ;eax = 0, usVar1 == 0
  1797. A - inc   eax            ;eax = 1, usVar1 == 0
  1798.      ---- switch threads ----
  1799. B - mov   eax, [usVar1]  ;eax = 0, usVar1 == 0
  1800. B - inc   eax            ;eax = 1, usVar1 == 0
  1801. B - mov   [usVar1],eax   ;eax == 1, usVar1 = 1
  1802.      ---- other processing ----
  1803.      ---- switch threads ----
  1804. A - mov   [usVar1],eax   ;eax == 1, usVar1 = 1
  1805.  
  1806. Figure 2) Accessing usVar1 by multiple threads 
  1807.  
  1808. Although at the end of two ++usVar1 instructions it should go from 0 to 2, the 
  1809. final value comes out to be 1. This is obviously not good. 
  1810.  
  1811. What you would want to do to solve this problem is to make sure your thread 
  1812. were not interrupted in the middle of using a variable, structure, or other 
  1813. piece of data.  This can be accomplished in two ways.  One way is to call 
  1814. DosEnterCritSec() before the calculation, and call DosExitCritSec() afterwards. 
  1815. This causes all thread switching to stop between the two function calls.  All 
  1816. threads.  The threads that control OS/2, other threads in your program, all 
  1817. threads in other programs, and all threads that handle interrupt processing. 
  1818. Use of these two functions may be fine for simple operations such as a single 
  1819. increment or decrement of a variable, but should never be used for processing 
  1820. that takes longer than just a few assembly language instructions. If you 
  1821. suspend system threads for too long you risk losing data coming in from the 
  1822. keyboard or serial ports, and you will prevent other updates that need to be 
  1823. done on a regular basis.  Besides, you are only really worried about threads A 
  1824. and B accessing a given piece of data. 
  1825.  
  1826. A much better solution is to use semaphores.  Semaphores come in three 
  1827. varieties:  mutually-exclusive (mutex), event, and multiple-wait.  Mutex 
  1828. semaphores are like a hall pass; only one thread may have the hall pass at any 
  1829. one time, and the others must wait until the pass is returned.  Event 
  1830. semaphores are like traffic lights where you can have a stop and a go status. 
  1831. Multiple wait semaphores are like a collection of the other two types; you have 
  1832. several hall passes or traffic lights to consider at the same time. 
  1833.  
  1834. Semaphores may also be private or shared, and named or unnamed.  Private 
  1835. semaphores may only be used by a single process; shared semaphores may be used 
  1836. by several processes.  Other processes may obtain the handle of a semaphore in 
  1837. a couple of ways.  The handle of the thread can be passed in a message.  If the 
  1838. semaphore is named, then the other process may use a known name to request the 
  1839. handle from the operating system. 
  1840.  
  1841. The programming samples in Gearing Up For Games will use only private, unnamed 
  1842. semaphores, so only they will be covered.  Also, we will not be using multiple 
  1843. wait semaphores.  For information on named and unnamed, private and shared, and 
  1844. multiple wait semaphores check out the OS/2 Toolkit documentation, or a good 
  1845. third party book on OS/2 programming. 
  1846.  
  1847. Mutex Semaphores 
  1848.  
  1849. Mutex semaphores allow two or more threads to take turns in accessing 
  1850. information.  First, the mutex semaphore must be created with 
  1851. DosCreateMutexSem().  Often it is convenient to do this in the main thread 
  1852. during initialization before any threads are even created.  When the semaphore 
  1853. is no longer needed, DosCloseMutexSem() is called.  This can also be done in 
  1854. the main thread during cleanup. 
  1855.  
  1856. When a thread wants to access a piece of information that two or more threads 
  1857. use, it calls DosRequestMutexSem().  If this function returns without error, 
  1858. then the thread "owns" the semaphore.  When this function is called, a timeout 
  1859. value is also specified.  The timeout value is the number of milliseconds that 
  1860. DosRequestMutexSem() will wait for the semaphore to become available.  If this 
  1861. time runs out, the function returns with a timeout error. The timeout value may 
  1862. also be given the values of SEM_IMMEDIATE_RETURN and SEM_INDEFINITE_WAIT.  An 
  1863. immediate return request means that the function will not wait for the 
  1864. semaphore at all.  An indefinite wait request means DosRequestMutexSem() will 
  1865. not return until it has gained ownership of the semaphore, and this is the 
  1866. setting we will use. 
  1867.  
  1868. When the thread is finished accessing the shared data, it calls 
  1869. DosReleaseMutexSem().  This allows another thread to have access to the data. 
  1870. If two or more threads are waiting for a semaphore when it is released, the 
  1871. thread with the highest priority gains control.  Note that an internal counter 
  1872. is kept for each semaphore that is incremented upon a request and decremented 
  1873. upon a release.  Therefore you must call DosReleaseMutexSem() for each time 
  1874. that you called DosRequestMutexSem(). 
  1875.  
  1876. Let's consider two threads, A and B, trying to use the variable ulVar1. During 
  1877. setup DosCreateMutexSem() is called and the handle is stored in hmtxSem1. 
  1878. Threads A and B run.  Thread A comes to a place where it needs ulVar1, so it 
  1879. calls DosRequestMutexSem() with the semaphore handle stored in hmtxSem1.  No 
  1880. other thread owns this semaphore, so A gains ownership.  It can now safely 
  1881. access ulVar1.  While thread A is using ulVar1, thread B comes to a place where 
  1882. it needs to access the same variable.  Thread B calls DosRequestMutexSem() with 
  1883. hmtxSem1 and an indefinate wait specified. However since A already owns the 
  1884. semaphore, thread B blocks.  When thread A finishes accessing ulVar1, it calls 
  1885. DosReleaseMutexSem().  Now thread B's call to DosRequestMutexSem() returns and 
  1886. thread B can safely access ulVar1. Thread B must release the semaphore when it 
  1887. is done accessing ulVar1. 
  1888.  
  1889. Mutex semaphores can also be used when one thread wants to stop another thread, 
  1890. but wants to let the second thread finish what it is doing.  An example of this 
  1891. is pausing a game.  The main loop of the game thread looks something like this: 
  1892.  
  1893. while (! bEndGameThread)
  1894.      {
  1895. DosRequestMutexSem (hmtxPause, SEM_INDEFINITE_WAIT);
  1896.      DosReleaseMutexSem (hmtxPause);
  1897.      // regulate the speed of the game
  1898.      // move player
  1899.      // move enemies
  1900.      // move bullets, etc.
  1901.      // compose graphics screen.
  1902.      // blit screen.
  1903.      };
  1904.  
  1905. Figure 3) Processing loop for a game thread 
  1906.  
  1907. Now the player presses a button that pauses the game.  The button press is 
  1908. intercepted by the message processing routine in the main thread.  It requests 
  1909. ownership of hmtxPause, and chances are that it will get it.  The game thread 
  1910. will finish blitting the frame that it is working on, and before it starts the 
  1911. next frame, it will request hmtxPause.  Since this semaphore is already owned 
  1912. by the main thread, the main game thread will block and the game will be 
  1913. paused; new positions will not be calculated, and new screens will not be 
  1914. blitted.  Note that this means that if the game is in a window and the window 
  1915. needs to be updated, then you will have to blit the last completed frame 
  1916. elsewhere.  Most likely this will be in the handling of the WM_PAINT message. 
  1917. When the player presses the button to unpause the game, the message handler in 
  1918. the main thread receives the request.  If the game is paused, then the main 
  1919. thread releases hmtxPause, and the game thread may continue.  Be certain to 
  1920. check to see if a game is paused or unpaused before requesting or releasing the 
  1921. semaphore, because you only want to have one request active at a time. 
  1922.  
  1923. Finally, you can use the function DosQueryMutexSem() to find out what (if any) 
  1924. process and thread owns the semaphore, as well as find out how many outstanding 
  1925. requests for the semaphore exist (including the request made by the thread that 
  1926. currently owns the semaphore). 
  1927.  
  1928. Event Semaphores 
  1929.  
  1930. Event semaphores are useful for one thread to let another know that something 
  1931. has happened.  They are also useful because they can be hooked up to timers, 
  1932. and the timer can use the semaphore to let a thread know when a certain time 
  1933. period has passed. 
  1934.  
  1935. Like mutex semaphores, event semaphores can be private or shared, named or 
  1936. unnamed.  You create an event semaphore with DosCreateEventSem(), and destroy 
  1937. it when you are finished with DosCloseEventSem().  This is usually done in the 
  1938. main thread during setup and cleanup respectively.  If you wish to hook a timer 
  1939. up to the semaphore, this can be done right after it is created with a call to 
  1940. DosStartTimer(). 
  1941.  
  1942. Event semaphores have two states:  posted and reset.  You post to an event 
  1943. semaphore when an event occurs, and you reset it when you want to clear it and 
  1944. wait for the next event.  The number of times an event semaphore is posted to 
  1945. is recorded and given upon request. 
  1946.  
  1947. You post an event semaphore with a call to DosPostEventSem(). If you have 
  1948. hooked the event semaphore up to a timer, then the timer will automatically 
  1949. post the semaphore after the requested period of time.  You clear the semaphore 
  1950. with DosResetEventSem(), and this call will return the number of times the 
  1951. semaphore was posted since the last reset. 
  1952.  
  1953. Although you can use DosQueryEventSem() to find out how many times it has been 
  1954. posted, most often you will check an event semaphore with DosWaitEventSem(). 
  1955. DosWaitEventSem() blocks a thread like DosRequestMutexSem(), and it acts much 
  1956. the same way.  You provide a timeout value, SEM_INDEFINITE_WAIT, or 
  1957. SEM_IMMEDIATE_RETURN.  If you specify an indefinite wait, the function will 
  1958. return immediately if the semaphore has already been posted, or it will block 
  1959. the calling thread until the semaphore is posted to by another thread or a 
  1960. timer.  After DosWaitEventSem() returns, you will probably want to immediately 
  1961. reset it so that you know if any new posts have been made between this and the 
  1962. next call to DosWaitEventSem(). DosResetEventSem() clears the number of posts 
  1963. to 0. 
  1964.  
  1965. Often you will use event semaphores and timers together.  There are only a 
  1966. limited number of timers available in OS/2.  These timers are hooked up not to 
  1967. the Programmable Interrupt Timer (PIT) that is usually reprogrammed in DOS 
  1968. games, but rather to a different hardware timer that I believe is also used for 
  1969. managing multitasking.  Although you request the time between timer posts in 
  1970. milliseconds, time is actually handled in units of clock ticks, which varies 
  1971. depending on the computer system.  For Intel based systems, the resolution of 
  1972. this timer is about 32 milliseconds, and this gives a rate of about 31 or 32 
  1973. posts per second. 
  1974.  
  1975. Before requesting a timer, you will want to make sure there are still some 
  1976. available.  The number of available timers can be found with a call to 
  1977. WinQuerySysValue() to find the value of SV_CTIMERS.  If no timers are 
  1978. available, you should exit the game with an error message.  You request a timer 
  1979. with a call to DosStartTimer() after you have created the event semaphore.  You 
  1980. pass the handle of the event timer to this function, along with a millisecond 
  1981. count.  Now the event semaphore will be posted every x milliseconds, with x 
  1982. being the value you specified in the call to DosStartTimer().  When you are 
  1983. done with the timer, you call DosStopTimer() to stop it and release it for 
  1984. another program to use. 
  1985.  
  1986. You can use event semaphores and timers to regulate the speed of your game. 
  1987. Let's consider an action game.  You want the game to run at a constant frame 
  1988. rate regardless of the speed of the computer it is running on.  Since the timer 
  1989. runs at around 32 posts per second, we will target our frame rate to this 
  1990. speed.  For faster frame rates we need a higher resolution timer.  I believe 
  1991. that at least two such timers currently exist; one is available on the DevCon 
  1992. Device Driver Kit and is designed for use by device drivers, and the other 
  1993. timer is accessed through the two DosTmr* functions.  The DosTmr* functions 
  1994. require 128-bit division and multiplication to use.  I have not used either of 
  1995. these timers yet however, so I will not cover them. 
  1996.  
  1997. To achieve a constant frame rate at the top of your main game loop, you check 
  1998. your timer.  If the timer interval has passed, you reset the timer and continue 
  1999. on.  Otherwise you wait until the required interval has passed.  With a timer 
  2000. and an event semaphore, you know the correct interval has passed when the 
  2001. semaphore is posted.  With a timer that only allows you to read it's value and 
  2002. doesn't generate interrupts, post messages, or post semaphores (such as the 
  2003. DosTmr* functions), you will need to check the elapsed time yourself.  If 
  2004. enough time has passed, update your timer variables and continue.  If not, you 
  2005. will have to continue to poll the timer since you don't have a function that 
  2006. blocks the current thread.  In order to keep the polling loop from burning up 
  2007. CPU time when it doesn't need to, call DosSleep (0) after every unsuccessful 
  2008. check. 
  2009.  
  2010. With the standard timer and event semaphore, our main game loop for an action 
  2011. game looks something like this: 
  2012.  
  2013. DosResetEventSem (hevTimerSem);
  2014. while (! bEndGameThread)
  2015.      {
  2016.      // check for paused game
  2017.      // regulate the speed of the game
  2018. DosWaitEventSet (hevTimerSem, SEM_INDEFINITE_WAIT);
  2019.      DosResetEventSem (hevTimerSem);
  2020.      // move player
  2021.      // move enemies
  2022.      // move bullets, etc.
  2023.      // compose graphics screen.
  2024.      // blit screen.
  2025.      };
  2026.  
  2027. Figure 4) Processing loop revisited 
  2028.  
  2029. One final note about blocking the game thread with either an event or a mutex 
  2030. semaphore.  When you request that the game ends (by setting bEndGameThread to 
  2031. true), then you must make sure the game thread is not blocked by either a pause 
  2032. or a speed regulating semaphore.  You must therefore release any mutex 
  2033. semaphores that the main thread owns, and post any event semaphores that the 
  2034. game thread is waiting on. 
  2035.  
  2036. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2037.  
  2038.  
  2039. ΓòÉΓòÉΓòÉ 7.3. Basic Sprites ΓòÉΓòÉΓòÉ
  2040.  
  2041. Basic Sprites 
  2042.  
  2043. I have not had time to write the Basic Sprite explanation for this article, but 
  2044. I have included the code.  I implemented sprite drawing in a very simple way. 
  2045. All sprites are stored in a PCX file.  This file is read into a canvas, and the 
  2046. canvas is passed to the sprite class.  Each sprite is defined as a rectangular 
  2047. region of the canvas.  When the sprite is drawn, the sprite is copied pixel by 
  2048. pixel from the sprite canvas over to the destination canvas. If the pixel's 
  2049. value is greater or equal to 248, then the pixel is not written, thus making 
  2050. those pixels clear since the background remains.  This makes the top 8 colors 
  2051. clear. 
  2052.  
  2053. The background is stored in it's own PCX file and read into it's own canvas. 
  2054. To erase the sprites, I just copy part of the background canvas over to the 
  2055. display canvas.  This covers everything that was written last time, and then 
  2056. the new sprites are written directly to the display canvas.  This display 
  2057. canvas is then blitted to the screen. 
  2058.  
  2059. Sprites are referenced with a book number and a sprite number.  A book is a 
  2060. collection of several sprites, up to 65,535 sprites per book.  There can be up 
  2061. to 255 books of sprites.  You would probably want to have a book of sprites for 
  2062. the player, a book for each of the enemies, and a book for missiles and 
  2063. explosions.  Each book will contain all of the frames of animation for that 
  2064. object. 
  2065.  
  2066. When we get into more advanced sprites, we will actually encode them from a 
  2067. canvas and store the encoded data.  Then we can discard the canvas the sprites 
  2068. were encoded from, thus saving memory.  Furthermore, encoded sprites will 
  2069. display much, much faster than the current method.  Also we will store the 
  2070. books of encoded sprites to disk in library files.  I will be explaining 
  2071. library files in the future when I cover organizing game data. 
  2072.  
  2073. The sprite class has a number of routines which are really just place holders 
  2074. for more advanced features.  If a function doesn't seem to have a use now then 
  2075. just ignore it; we will come back to it in the future. 
  2076.  
  2077. The Canvas Class 
  2078.  
  2079. One small addition has been made to the canvas class as well.  I have added the 
  2080. routine CopyDirtyRec(), and this copies a rectangle from one canvas to another. 
  2081. This routine is used to copy part of the background canvas to the display 
  2082. canvas when the display canvas needs to be erased.  The code of this routine is 
  2083. a good demonstration of how to move canvas data around, and some of the 
  2084. speedups that canvases allow. 
  2085.  
  2086. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2087.  
  2088.  
  2089. ΓòÉΓòÉΓòÉ 7.4. Those Silly Bugs ΓòÉΓòÉΓòÉ
  2090.  
  2091. Those Silly Bugs 
  2092.  
  2093. The MAKEFILE that accompanied my last article appears to have had a slight bug 
  2094. in it.  In calling the linker, I neglected to put the full path name before the 
  2095. "mmpm2.lib" file.  Therefore "libr mmpm2.lib" should read "libr 
  2096. c:\toolkit\lib\mmpm2.lib" or add whatever path you have to the lib directory of 
  2097. the OS/2 toolkit. 
  2098.  
  2099. Aside from that, I don't think there were any other bugs in the article for 
  2100. EDM/2 3-7.  Am I mistaken? 
  2101.  
  2102. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2103.  
  2104.  
  2105. ΓòÉΓòÉΓòÉ 7.5. News and other Nonsense ΓòÉΓòÉΓòÉ
  2106.  
  2107. News and other Nonsense 
  2108.  
  2109. By the time you read this, the Entertainment Toolkit for OS/2 may already be 
  2110. out on DevCon 8. It was not yet available at press time, so I am unable to 
  2111. cover anything on it with any certainty.  I will be writing about it in the 
  2112. near future. 
  2113.  
  2114. If you haven't visited it yet, I'd like to suggest that you drop by IBM's Games 
  2115. Home Page.  The URL is http://www.austin.ibm.com/os2games and you will need a 
  2116. Web browser to look at it.  IBM seems to be using this as their main 
  2117. notification to the public (that's us) of game related information, so it makes 
  2118. good sense to check it out every week or so for new stuff.  Recently the beta 
  2119. documentation for the Entertainment Toolkit has been placed on this site, as 
  2120. well as the joystick drivers and documentation and other stuff. 
  2121.  
  2122. While we're on the topic of Web pages, I have finally put one up of my own. I 
  2123. hope to eventually have online versions of my EDM/2 articles up there, and I 
  2124. may even be placing code and text on the web page before it sees print in 
  2125. EDM/2.  The page is really, really sparse right now, but it should grow as I 
  2126. find time to work on it.  I also have a number of OS/2 game related links on my 
  2127. page already that you may want to check out. 
  2128.  
  2129. This month I also did things a little bit differently in that I didn't 
  2130. distribute duplicates of code from previous articles when the code didn't 
  2131. change at all.  The README.1ST file in the code archive will tell you which 
  2132. files you need from the last article.  Simply place those files in the 
  2133. directory with the new code, and run the makefile (if of course you are using 
  2134. the Watcom compiler, otherwise the makefile will not work). 
  2135.  
  2136. Next month I hope to cover sprites in depth, including how to construct, store, 
  2137. and display Run Length Encoded (RLE) sprites, and how to clip sprites. If I 
  2138. have time, I may show how dirty rectangles can be used in some cases to speed 
  2139. up sprite updating, though with a full scrolling background dirty rectangles 
  2140. don't do us much good.  Also I should be able to cover DIVE's fullscreen 
  2141. abilities in the 320x200x256 color mode, since they are a breeze to implement. 
  2142.  
  2143. As always, I welcome comments.  You can reach me at mduffy@ionet.net, or find 
  2144. me lurking on comp.os.os2.games among other places.  Until next time... 
  2145.  
  2146. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2147.  
  2148.  
  2149. ΓòÉΓòÉΓòÉ 8. Inside INF ΓòÉΓòÉΓòÉ
  2150.  
  2151. Inside INF 
  2152.  
  2153. Written by Peter Childs 
  2154.  
  2155. Introduction 
  2156.  
  2157. The Problem 
  2158.  
  2159. As I sat debating the approach I would adopt for this article it became 
  2160. distressingly obvious that there would be only a small audience of fanatics 
  2161. that would share my enthusiasm for the intricate details of the INF file 
  2162. format. 
  2163.  
  2164. I also had to painfully admit that others would not even know that INF/HLP 
  2165. files are the backbone of OS/2's online help system, and that most of those 
  2166. that did would be quite happy to consider the issue finished at that point. 
  2167.  
  2168. The Solution 
  2169.  
  2170. In this article I will attempt to present a overview of the OS/2 INF/HLP file 
  2171. format in such a manner that a cursory read will leave the reader with a 
  2172. general idea of the file format.  I will also explain some of the compression 
  2173. ideas used in the INF files and provide additional information for those 
  2174. wishing to investigate deeper. 
  2175.  
  2176. As my talents as a programmer are fairly limited I will not include large 
  2177. chunks of source.  I am, however, working on developing some C++ classes to 
  2178. allow easy access to the information in INF files.  If there is sufficient 
  2179. demand I may do an article showing the possible use of these classes. 
  2180.  
  2181. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2182.  
  2183.  
  2184. ΓòÉΓòÉΓòÉ 8.1. What does it mean? ΓòÉΓòÉΓòÉ
  2185.  
  2186. What does it mean? 
  2187.  
  2188. Some Basic Terms 
  2189.  
  2190. In this document we will be discussing the INF/HLP file format. 
  2191.  
  2192. INF files and HLP files are basically identical with the exception that INF 
  2193. files are generally designed to be viewed with the view.exe program, like this 
  2194. magazine, and HLP files are developed to provide online help for applications. 
  2195. To the best of my knowledge the file format is identical except for a single 
  2196. flag bit.  From here on, when I refer to INF files I mean both INF and HLP 
  2197. files. 
  2198.  
  2199. INF files are compiled with the IPFC (Information Presentation Facility 
  2200. Compiler) available with most OS/2 compilers, and the OS/2 Tool kits.  The 
  2201. source used is a form of fairly simple markup, with the power to do just about 
  2202. anything you could want. 
  2203.  
  2204. The IPF Online Reference (1st Ed 1994) describes IPF: 
  2205.  
  2206. The Information Presentation Facility (IPF) is a tool that enables you to 
  2207. create online information, to specify how it will appear on the screen, to 
  2208. connect various parts of the information, and to provide help information that 
  2209. can be requested by the user. 
  2210.  
  2211. It is important to realize the difference between IPF source markup, and INF 
  2212. files.  The INF files are the compiled versions, and the difference is as 
  2213. marked as the difference between C source and an executable.  The IPF source 
  2214. markup is well documented, whereas the INF file format is not officially 
  2215. documented. 
  2216.  
  2217. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2218.  
  2219.  
  2220. ΓòÉΓòÉΓòÉ 8.2. In the beginning ΓòÉΓòÉΓòÉ
  2221.  
  2222. In the beginning 
  2223.  
  2224. The Header 
  2225.  
  2226. The header is described here as a structure.  When I began playing with INF 
  2227. files I just defined this structure and then read 155 bytes into it starting at 
  2228. offset 0. Although this worked fine for Borland C++ I had to muck with things 
  2229. with gcc to force the structure to be packed. 
  2230.  
  2231. Most compilers offer a method of packing structures but if your code has to be 
  2232. portable then you will also have to consider the big-endian / small-endian 
  2233. stuff (ie.  the bytes are stored differently in memory on Sparcs than PCs). 
  2234. Although probably obvious to most programmers, this had me stumped! 
  2235.  
  2236. Starting at file offset 0 the following structure resembles the header 
  2237. (packed): 
  2238.  
  2239. struct os2infheader
  2240. {
  2241.      int_16 ID;           // ID magic word (5348h = "HS")
  2242.      int_8  unknown1;     // unknown purpose, could be third letter of ID
  2243.      int_8  flags;  // probably a flag word...
  2244.                     //  bit 0: set if INF style file
  2245.                     //  bit 4: set if HLP style file
  2246.                     // patching this byte allows reading HLP files
  2247.                     // using the VIEW command, while help files
  2248.                     // seem to work with INF settings here as well.
  2249.      int_16 hdrsize;      // total size of header
  2250.      int_16 unknown2;     // unknown purpose
  2251.      int_16 ntoc;         // 16 bit number of entries in the tocarray
  2252.      int_32 tocstrtablestart;  // 32 bit file offset of the start of the
  2253.                                // strings for the table-ofcontents
  2254.      int_32 tocstrlen;    // number of bytes in file occupied by the
  2255.                           // table-of-contents strings int_32 tocstart;
  2256.                           // 32 bit file offset of the start of tocarray
  2257.      int_16 nres;         // number of panels with resource numbers
  2258.      int_32 resstart;     // 32 bit file offset of resource number table
  2259.      int_16 nname;        // number of panels with textual name
  2260.      int_32 namestart;    // 32 bit file offset to panel name table
  2261.      int_16 nindex;       // number of index entries
  2262.      int_32 indexstart;   // 32 bit file offset to index table
  2263.      int_32 indexlen;     // size of index table
  2264.      int_8  unknown3[10]; // unknown purpose
  2265.      int_32 searchstart;  // 32 bit file offset of full text search table
  2266.      int_32 searchlen;    // size of full text search table
  2267.      int_16 nslots;       // number of "slots"
  2268.      int_32 slotsstart;   // file offset of the slots array
  2269.      int_32 dictlen;      // number of bytes occupied by the "dictionary"
  2270.      int_16 ndict;        // number of entries in the dictionary
  2271.      int_32 dictstart;    // file offset of the start of the dictionary
  2272.      int_32 imgstart;     // file offset of image data
  2273.      int_8  unknown4;     // unknown purpose
  2274.      int_32 nlsstart;     // 32 bit file offset of NLS table
  2275.      int_32 nlslen;       // size of NLS table
  2276.      int_32 extstart;     // 32 bit file offset of extended data block
  2277.      int_8  unknown5[12]; // unknown purpose
  2278.      char8 title[48];     // ASCII title of database
  2279. }
  2280.  
  2281. Figure 1) INF header structure 
  2282.  
  2283. Most of these values come in handy. 
  2284.  
  2285. Our Sample File 
  2286.  
  2287. Below is a simple IPF (source) file which I have compiled into a INF for use in 
  2288. examples. 
  2289.  
  2290. :userdoc.
  2291. :title. Sample INF file...
  2292. :h1.Header One
  2293. :p.This is a test. Os/2, lies, and Windows 95.
  2294. :p.1234.5
  2295. :artwork name='in_inf.bmp'.
  2296. Hello
  2297. :p.
  2298. :artwork name='tocarray.bmp'.
  2299. :i1. This is a index entry
  2300. :euserdoc.
  2301.  
  2302. Figure 2) Sample IPF file 
  2303.  
  2304. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2305.  
  2306.  
  2307. ΓòÉΓòÉΓòÉ 8.3. Master Dictionary ΓòÉΓòÉΓòÉ
  2308.  
  2309. Master Dictionary 
  2310.  
  2311. Each INF file has a master dictionary which holds all of the words and symbols 
  2312. used in the articles that make up the INF file.  The dictionary starts at 
  2313. offset dictstart, has a length dictlen, and comprises of ndict words. 
  2314.  
  2315. Figure 3) Master dictionary layout (in the file) 
  2316.  
  2317. In the example case above the dictionary is like this: 
  2318.  
  2319. [0] : (,)
  2320. [1] : (.)
  2321. [2] : (/)
  2322. [3] : (1234)
  2323. [4] : (2)
  2324. [5] : (5)
  2325. [6] : (95)
  2326. [7] : (a)
  2327. [8] : (and)
  2328. [9] : (Hello)
  2329. [10] : (is)
  2330. [11] : (lies)
  2331. [12] : (Os)
  2332. [13] : (test)
  2333. [14] : (This)
  2334. [15] : (Windows)
  2335.  
  2336. Figure 4) Master dictionary for the IPF sample 
  2337.  
  2338. Some things to note are that the source contains the word Os/2, whereas the 
  2339. dictionary contains the words '/', '2', and 'Os'. 
  2340.  
  2341. One way of loading the dictionary is detailed below (C++ code snippet). 
  2342.  
  2343. dict = new char*[ infHeader.ndict ]; // our array of pointers
  2344.  
  2345. // change all length bytes to '\0' and set pointers
  2346. // to start of each word
  2347. while( i < infHeader.dictlen && j < infHeader.ndict )
  2348.      {
  2349.      add = dictstore[i];
  2350.      dict[j++] = &( dictstore[i+1] );
  2351.      dictstore[i] = '\0';
  2352.      i += add;
  2353.      }
  2354.  
  2355. Figure 5) C++ code for loading the dictionary 
  2356.  
  2357. The method used is irrelevant but you need some way of mapping i to the i'th 
  2358. element of the dictionary.  Also don't forget to delete the allocated memory if 
  2359. you use the above sample with: 
  2360.  
  2361. delete[] dictstore;
  2362. delete[] dict;
  2363.  
  2364. Figure 6) C++ to delete the dictionary 
  2365.  
  2366. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2367.  
  2368.  
  2369. ΓòÉΓòÉΓòÉ 8.4. Articles ΓòÉΓòÉΓòÉ
  2370.  
  2371. Articles 
  2372.  
  2373. Each article in an INF file is comprised of one or more slots.  There are 
  2374. several structures that deal with slots.  One is a array of offsets mapping i 
  2375. to the i'th slot's position in the file.  Another is also the structure of the 
  2376. slot itself.  Each slot also has a local dictionary that maps items in the slot 
  2377. to words in the master dictionary. 
  2378.  
  2379. The Slots Array 
  2380.  
  2381. Beginning at file offset slotsstart (from the header) there is an array of 
  2382. int32's.  These are offsets in the INF file in which the i'th slot can be 
  2383. found. 
  2384.  
  2385. int_32 slots[nslots]
  2386.  
  2387. Figure 7) Slots area declaration 
  2388.  
  2389. The Slots Themselves 
  2390.  
  2391. Beginning at the file offset slots[i] the following structure can overlay the 
  2392. file: 
  2393.  
  2394. {
  2395.      int_8  stuff;         // ?? [always seen 0]
  2396.      int_32 localdictpos;  // file offset  of  the  local dictionary
  2397.      int_8  nlocaldict;    // number of entries in  the local dictionary
  2398.      int_16 ntext;         // number of bytes in the text
  2399.      int_8  text[ntext];   // encoded text of the article
  2400. }
  2401.  
  2402. Figure 8) Slots structure 
  2403.  
  2404. The Local Dictionary 
  2405.  
  2406. The local dictionary is used to map items in the encoded text of the slot to 
  2407. words in the master dictionary.  Take note that the nlocaldict variable in a 
  2408. slot's structure is a byte in size, hence a single slot can only have a maximum 
  2409. of 255 (really 250 - we'll discuss that later) different words from the master 
  2410. dictionary in it. 
  2411.  
  2412. Beginning at file offset localdictpos (for each article) there is an array: 
  2413.  
  2414. int_16 localdict[nlocaldict]
  2415.  
  2416. Figure 9) Local dictionary declaration 
  2417.  
  2418. The Text Itself 
  2419.  
  2420. The encoded text is decoded somewhat like the following: 
  2421.  
  2422. bool space = TRUE;
  2423. while( i++ < ntext )
  2424.      switch( text[i] )
  2425.      {
  2426.           case  0xfa: // end of paragraph, sets space  to TRUE
  2427.                break;
  2428.           case 0xfb: // [unknown]
  2429.                break;
  2430.           case 0xfc: // spacing = !spacing
  2431.                break;
  2432.           case 0xfd: // line break, set space to TRUE if not monospaced
  2433.                            // example
  2434.                break;
  2435.           case 0xfe: // space
  2436.                break;
  2437.           case 0xff: // escape code
  2438.                break;
  2439.           default:   // output dict[localwords[text[i]]] and, if
  2440.                            // space==TRUE a space.
  2441.                break;
  2442.      }
  2443.  
  2444. Figure 10) Sample code for decoding text 
  2445.  
  2446. It is pretty obvious that this doesn't leave a lot of space for formatting 
  2447. commands.  This is where the escape codes come in.  The general format for an 
  2448. escape code is: 
  2449.  
  2450. {
  2451.      int_8  FF;          // always equals 0xFF
  2452.      int_8  esclen;      // length of sequence
  2453.                //   (including esclen, excluding 0xFF)
  2454.      int_8  escCode;  // which escape code
  2455. }
  2456.  
  2457. Figure 11) Escape codes structure 
  2458.  
  2459. These escape codes define things like setting margins, inter document links, 
  2460. and the like.  We will ignore them here for the moment.  There are described in 
  2461. the inf03.txt. 
  2462.  
  2463. So Show Me Something That Works! 
  2464.  
  2465. Ok, here's a snippet that shows the basic idea behind decoding slots.  For the 
  2466. sake of simplicity we ignore most of the nasty stuff.  You should also note 
  2467. that although each slot contains some text - the way these slots fit together 
  2468. is described next in Table of Contents. 
  2469.  
  2470. Included with this issue of EDM/2 is the source for a small program, called 
  2471. exttext.cc, that extracts all the textual information from an INF file.  Also 
  2472. included is a simple INF header class. 
  2473.  
  2474. A few quick notes I've noticed about decoding articles that isn't mentioned in 
  2475. the inf02a.doc.  When you decode multi- slots articles, the state of SPACE (ie 
  2476. true or false) is retained between the article and the next.  Basically, 
  2477. although the local dictionary changes, pretend that each document is merge onto 
  2478. the next -- with regard to settings like the left and right margins, fonts, 
  2479. colours, font styles, and space. 
  2480.  
  2481. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2482.  
  2483.  
  2484. ΓòÉΓòÉΓòÉ 8.5. Table of Contents ΓòÉΓòÉΓòÉ
  2485.  
  2486. Table of Contents 
  2487.  
  2488. The Table of contents is created by loading in an array of [ntoc] 32-bit 
  2489. offsets, starting at offset tocstart. 
  2490.  
  2491. At the offset ( tocentrystart[i] ) a toc entry structure is located that 
  2492. contains information including the title, the items level in the table of 
  2493. contents, if it is hidden or not, and, most importantly, how many and which 
  2494. slots make up the item.  There is also a 'has_children' flag which if true 
  2495. means the following entry has a higher level. 
  2496.  
  2497. Figure 12) TOC (Table of Contents) entries 
  2498.  
  2499. Index 
  2500.  
  2501. The index is pretty simple and relies on table of contents a fair bit. 
  2502. Beginning at file offset indexstart there is nindex structures like the 
  2503. following stored. 
  2504.  
  2505. {
  2506.      int_8     nword;       // size of name
  2507.      int_8     level;       // indent level
  2508.      int_8     stuff;
  2509.      int_16    toc;         // toc entry number of panel
  2510.      char8     word[nword]; // index word [not zero-terminated]
  2511. }
  2512.  
  2513. Figure 13) Index structure 
  2514.  
  2515. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2516.  
  2517.  
  2518. ΓòÉΓòÉΓòÉ 8.6. Bitmaps ΓòÉΓòÉΓòÉ
  2519.  
  2520. Bitmaps 
  2521.  
  2522. I am only going to cover this at a superficial level.  I am only going to 
  2523. describe the compression used in newer INF files.  The older (ie.  v1.3 etc) 
  2524. INF files use a proprietary compression scheme. 
  2525.  
  2526. The newer INF files use a LZW based compression scheme.  This scheme is 
  2527. basically the same as the one covered in 'LZW Revisited' (Dr.Dobbs June 1990). 
  2528. You must alter the decompression code to use MAX_BITS 12 or you will spend a 
  2529. long time figuring out that after that last input byte 512 your output is all 
  2530. wrong [grin]. 
  2531.  
  2532. Getting Started 
  2533.  
  2534. There seems to be no array of bitmap offsets in the file anywhere but there is 
  2535. a general start for the image information - imgstart. 
  2536.  
  2537. Here's the basic rundown on decompression: 
  2538.  
  2539. When during the decompression of a slot you come across a sequence something 
  2540. like  0xff + 0x07 + 0x0E + 0x01 + 0x00 + 0x00 + 0x00 + 0x00 
  2541.  
  2542. you know is an escape code (0xff) of length 7 bytes (0x07); that code is for a 
  2543. bitmap/metafile (0x0E).  The next byte is the flags byte and it breaks down 
  2544. like this: 
  2545.  
  2546. if( items[i] & 0x01 ) printf ("Left ");   // 00000001
  2547. if( items[i] & 0x02 ) printf ("Right ");  // 00000010
  2548. if( items[i] & 0x04 ) printf ("Center "); // 00000100
  2549. if( items[i] & 0x08 ) printf ("Fit ");    // 00001000
  2550. if( items[i] & 0x10 ) printf ("Runin ");  // 00010000
  2551.  
  2552. Figure 14) Alignment for bitmaps 
  2553.  
  2554. The next four bytes are a 32-bit offset from imgstart to the bitmap/metafile. 
  2555. (i.e.  you do a is.seekg( imgstart + offset ) Also remember again here that if 
  2556. you are writting for cross platform support you'll have to deal with the big- 
  2557. endian, little-endian issue.) 
  2558.  
  2559. The Bitmap Header and Colour table 
  2560.  
  2561. If you do the seek and read in the next two bytes you'll be able to know what 
  2562. sort of image comes next.  mf means a metafile (I think - I haven't seen one!). 
  2563. BM means the old bitmap compression, and bM is the one that we are happy to 
  2564. see. 
  2565.  
  2566. So, if everything is OK (ie 'bM') then read in a basic OS2BITMAP_FILEHEADER and 
  2567. OS2BITMAP_INFOHEADER.  Something like this: 
  2568.  
  2569. { // BITMAP FILE HEADER
  2570.      char8     usType[2];   // = 'bM';
  2571.      int_32    cbSize;
  2572.      int_16    xHotSpot;
  2573.      int_16    yHotSpot;
  2574.      int_32    offBits;     // =size(hdr)+size(colortbl)
  2575.      // BITMAP INFO HEADER
  2576.      int_32    cbFix;       // =size(info_hdr) (usually = 12?)
  2577.      int_16    cx;          // x size
  2578.      int_16    cy;          // y size
  2579.      int_16    cPlanes;     // color planes
  2580.      int_16    cBitCount;
  2581. }
  2582.  
  2583. Figure 15) Bitmap information structure 
  2584.  
  2585. A quick note that if you are going to use this structure "as is" to dump to a 
  2586. bitmap then you'll have to change the offBits like: 
  2587.  
  2588. offBits = 14 + 12 + ( 3 * ( 1 << cBitCount ) );
  2589.  
  2590. Figure 16) Code change to use structure in figure 15 
  2591.  
  2592. Next up after the header comes the colour table which is basically an array of 
  2593. ( 1 << cBitCount ) RGB entries (well actually 1 byte Blue, 1 byte Green, 1 byte 
  2594. Red) 
  2595.  
  2596. Data Blocks 
  2597.  
  2598. Next up (after all that) comes the Master Data Block, and one (or more) minor 
  2599. data blocks - each with their own compression type. 
  2600.  
  2601. { // Master Data Block
  2602.    int_32 num_to_follow;      // total number of bytes to follow
  2603.    int_16 uncompressed_bytes; // uncompressed bytes in each block
  2604. }
  2605. { // Minor Data Block
  2606.    int_16 x_bytes_to_follow;  // number of bytes in this block (to follow)
  2607.    int_8  comp_type;          // compression type 0=uncompressed, 2=lzw-based
  2608. }
  2609.  
  2610. Figure 17) Data block structures 
  2611.  
  2612. To help with your understanding here is the output from a program I wrote while 
  2613. working out the decompression routine. 
  2614.  
  2615. [Editor's note - my word processor completely destroyed the alignment that was 
  2616. present in the output, so I feel forced to delete it.  My apologies.] 
  2617.  
  2618. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2619.  
  2620.  
  2621. ΓòÉΓòÉΓòÉ 8.7. Parting words ΓòÉΓòÉΓòÉ
  2622.  
  2623. Parting words 
  2624.  
  2625. All my knowledge of the INF file format stemmed from the work of others.  I 
  2626. hopefully have added some small bits of useful information and my motivation 
  2627. for writing this article is to make that information available to others. 
  2628.  
  2629. The document that encouraged me into investigating the INF file format is 
  2630. available at ftp://hobbes.nmsu.edu/os2/dev32/inf02a.doc and was authored by 
  2631. Carl Hauser, and updated by Marcus Groeber.  I lifted lots of stuff out of it 
  2632. for this article and have included inf03.txt as a slightly updated version. 
  2633.  
  2634. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2635.  
  2636.  
  2637. ΓòÉΓòÉΓòÉ 9. OS/2 Warp Game Developer's Seminar ΓòÉΓòÉΓòÉ
  2638.  
  2639. OS/2 Warp Game Developer's Seminar 
  2640.  
  2641. Written by Dave Briccetti 
  2642.  
  2643. Introduction 
  2644.  
  2645. On August 16th, 1995, I attended the OS/2 Warp Game Developer's Seminar, 
  2646. presented by the IBM Solution Partnership Center with speakers from the IBM 
  2647. Personal Software Products Boca Raton lab.  The Seminar was held in San Mateo, 
  2648. near San Francisco.  This is a brief report about my experiences at that event. 
  2649.  
  2650. I have no association with any of the products or companies mentioned herein, 
  2651. except that I'm a member of several IBM vendor support programs. 
  2652.  
  2653. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2654.  
  2655.  
  2656. ΓòÉΓòÉΓòÉ 9.1. Presentations ΓòÉΓòÉΓòÉ
  2657.  
  2658. Presentations 
  2659.  
  2660. After a continental breakfast I took a seat with about 80 other developers in 
  2661. the classroom at the Solution Partnership Center.  Like the airlines, IBM had 
  2662. overbooked the event, but they weren't offering free future classes to people 
  2663. who would go away.  (Their classes are free anyway.) 
  2664.  
  2665. Welcome & Introduction 
  2666.  
  2667. E.  Lloyd Webber, Worldwide Games Brand Manager from Boca Raton, Florida, 
  2668. started the presentations.  Lloyd announced the OS/2 Warp Entertainment Toolkit 
  2669. Beta 1, which is part of the now shipping Developers Connection 8. He made it 
  2670. very clear that IBM wants to help game developers, and told us that they want 
  2671. to hear from us about how they can help us. 
  2672.  
  2673. Video Performance 
  2674.  
  2675. Next up was one of the Entertainment Toolkit developers, Luis Rodriguez, on 
  2676. video performance with Direct Interface Video Extensions (DIVE).  Luis showed 
  2677. an animated jet fighter in a window (some of you have seen this before), and it 
  2678. was running so fast it was just a blur.  It was running at around 135 frames 
  2679. per second.  Maximized on the 640 x 480 desktop it was about 36 frames per 
  2680. second. 
  2681.  
  2682. Luis took us through the steps involved in using DIVE from a program.  I won't 
  2683. go into the details since they are documented very well elsewhere.  Take a look 
  2684. at the IBM OS/2 Games Home Page for more information.  See the last section of 
  2685. this report for the URL. 
  2686.  
  2687. One interesting feature of the toolkit allows a PM game developer to switch to 
  2688. full-screen modes such as 320 x 200, which is typical for games, and get the 
  2689. same performance as DOS games while still using the PM architecture. 
  2690.  
  2691. 3D Graphics (BRender) 
  2692.  
  2693. After a break we had a fascinating and awesome demonstration of BRender, a 3D 
  2694. real-time, high performance rendering program, an evaluation copy of which is 
  2695. included with the toolkit.  BRender stands for `Blazing Render,' and it truly 
  2696. blazes.  Rich Seidner of Argonaut Technologies (formerly with IBM and then 
  2697. Kaleida) showed the product, along with several games such as FX Fighter which 
  2698. use BRender. 
  2699.  
  2700. Here the topic drifted far from OS/2 as people asked esoteric questions about 
  2701. other platforms, and most of the stuff Rich showed was under DOS. Nonetheless, 
  2702. the technology is fascinating, and running under OS/2. 
  2703.  
  2704. Rich announced a special offer:  For a limited time, developers may license 
  2705. BRender for unlimited, royalty-free use under OS/2 for a onetime fee of $2,000. 
  2706. For multi- platform use, the fee is $10,000. 
  2707.  
  2708. Lunch and Technology Demos 
  2709.  
  2710. IBM fed us sandwiches and cookies and we wandered around to various rooms where 
  2711. we could meet the toolkit developers and other IBMers from Boca and Austin. 
  2712. One of those developers was Mike Brown, the author of PMMPEG, a program to 
  2713. display MPEG movies.  Several months ago Mike added DIVE support to PMMPEG, and 
  2714. he showed me the difference.  The color and speed improvements are quite 
  2715. impressive. 
  2716.  
  2717. I also saw programs with the new network games APIs demonstrated.  There were 
  2718. some glitches but the concept is pretty cool:  OS/2 APIs to connect players up 
  2719. to a game over the internet. 
  2720.  
  2721. Presentations, Continued 
  2722.  
  2723. Audio 
  2724.  
  2725. Next up was Larry Kyrala who talked about Direct Audio and real-time MIDI. 
  2726. These features allow more precise control over audio in the dynamic game 
  2727. environment.  One buzzword I heard was `score richening.'  I think this means 
  2728. that when you're getting your butt kicked in a game the music gets louder and 
  2729. busier. 
  2730.  
  2731. Input Devices 
  2732.  
  2733. Herman Rodriguez was the next speaker.  Herman leads the toolkit development 
  2734. team.  He struck me as being very knowledgeable and capable.  In this segment 
  2735. he talked about device driver support for generic input devices, and joysticks 
  2736. specifically.  He has developed an API which not only supports current analog 
  2737. joysticks, but which will support new digital joysticks being developed.  He 
  2738. said his goal was to generalize the interface to support devices such as data 
  2739. gloves. 
  2740.  
  2741. Multi-player Network 
  2742.  
  2743. The toolkit includes warpnet.dll, which provides an API to support multi-player 
  2744. games over a network.  The API currently supports TCP/IP.  There are functions 
  2745. such as WarpNetInitialize, Open, Broadcast, PackSend, PackRecv, and Close. 
  2746. Herman Rodriguez made this presentation. 
  2747.  
  2748. Technology Demos 
  2749.  
  2750. After the presentations we were invited to wander around and meet the 
  2751. developers and look at their demonstrations.  I saw an early version of 
  2752. Avarice, from Stardock Systems.  It has stunning graphics, but the guy running 
  2753. it (an attendee like myself) didn't know how to run it and we just didn't get 
  2754. it.  It was very soothing and mellow, but I'm a Dark Forces kind of guy, I 
  2755. guess.  Psygnosis' Lemmings for OS/2 was cute.  SimTown was there but I didn't 
  2756. see it.  I think I saw Star Emperor, which I believe is the follow-on to the 
  2757. highly successful Galactive Civilizations.  It looked good.  Conclusion 
  2758.  
  2759. I very much enjoyed taking a day and immersing myself in this new entertainment 
  2760. development technology.  I remain convinced that IBM is committed to supporting 
  2761. OS/2 developers.  IBM's developers of this new technology appear quite 
  2762. knowledgeable, and they obviously enjoy what they're doing.  Now let's see if I 
  2763. can satisfy my own creative needs and develop something fun! 
  2764.  
  2765. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2766.  
  2767.  
  2768. ΓòÉΓòÉΓòÉ 9.2. More Information ΓòÉΓòÉΓòÉ
  2769.  
  2770. More Information 
  2771.  
  2772. I can be reached at daveb@netcom.com, and 74475,1072 on CompuServe, or by phone 
  2773. at 510 945-7565, Ext.  210.  My WWW home page is http://www.best.com/~daveb. 
  2774.  
  2775. The location of the HTML version of this document is 
  2776. http://www.best.com/~daveb/Programming/gamedev.html. 
  2777.  
  2778. The IBM OS/2 Games Home Page is http://www.austin.ibm.com/os2games. 
  2779.  
  2780. Herman Rodrigues, Toolkit Manager:  hermanr@vnet.ibm.com.
  2781. Rich Seidner, Argonaut:  rich@argonaut.com.
  2782. Bradley Wardell, Stardock Systems:  wardell@ibm.net.
  2783.  
  2784. IBM Solution Partnership Center -- West
  2785. 2929 Campus Drive, Suite 275
  2786. San Mateo CA 94403
  2787. 1-800-678-4249 or 1-415-312-0240
  2788. fax 1-415-312-0254
  2789.  
  2790. IBM Solution Partnership Center, OS/2 Program Manager, Keith
  2791. Lew, kflew@sfovmic1.vnet.ibm.com.
  2792.  
  2793. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2794.  
  2795.  
  2796. ΓòÉΓòÉΓòÉ 10. Plugging into OS/2 Socket Programming ΓòÉΓòÉΓòÉ
  2797.  
  2798. Plugging into OS/2 Socket Programming 
  2799.  
  2800. Written by Edward D. Boykin 
  2801.  
  2802. Introduction 
  2803.  
  2804. Heya!  I would like to welcome you folks to a new series of EDM/2 articles on 
  2805. Client/Server programming with OS/2 Warp.  Client/Server programming 
  2806. encompasses a whole slew of different forms; so, for now, this series will 
  2807. focus entirely on the peer-to-peer LAN protocol referred to as "sockets". 
  2808.  
  2809. I am guessing that there will be three or four articles in this series but 
  2810. there might be more or less depending on how well I feel I am covering the 
  2811. topics.  This is my first shot at writing anything even remotely like this so 
  2812. if I stumble some please bear with me.  Thanks! 
  2813.  
  2814. If anybody notices some errors or better ways of doing some of the things I am 
  2815. doing please feel free to e-mail me.  The same goes if you have any questions 
  2816. on any of the subjects discussed here. 
  2817.  
  2818. I must also make another apology.  The code I use here is based on the IBM 
  2819. TCP/IP Development Toolkit which is a commercial product.  I am therefore 
  2820. unable to distribute the header files needed to compile the source code.  I 
  2821. have included copies of the executables so that you may see the results of the 
  2822. code.  The executables are compiled with full debugging on so you can step 
  2823. through it if you have the IPMD debugger.  I would make the code portable 
  2824. between EMX and C- Set++ but I don't have the time. 
  2825.  
  2826. Path of Study 
  2827.  
  2828. Over the next few months I will cover everything necessary for you to get 
  2829. started in socket programming.  The articles will start with a very simple 
  2830. client and server program which I will then develop into a basic message system 
  2831. allowing multiple client connections to a single server.  It will allow the 
  2832. people on the client end to connect to the server and chat with anyone else 
  2833. connected to the same server in near real-time. 
  2834.  
  2835. However, we have to walk before we can run.  This month I will start with an 
  2836. introduction to the basic functions in the socket API.  These are the minimal 
  2837. functions that are necessary to create the most basic client and server 
  2838. programs.  I have included just such a set of programs and encourage you to 
  2839. examine them while you read through this article. 
  2840.  
  2841. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2842.  
  2843.  
  2844. ΓòÉΓòÉΓòÉ 10.1. What is a Socket? ΓòÉΓòÉΓòÉ
  2845.  
  2846. What is a Socket? 
  2847.  
  2848. History 
  2849.  
  2850. Back in 1981, sockets were first introduced as the UNIX BSD 4.2 generic 
  2851. interface that would provide point to point communications for TCP/IP networks. 
  2852. After a couple of revisions and some stiff competition from other similar 
  2853. protocols, the socket API has become a very prevalent peer to peer protocol. 
  2854. This is good because it means my articles are not wasted electrons. 
  2855.  
  2856. Anyway, since then support for sockets has migrated to just about every 
  2857. operating environment including MS-DOS, OS/2, UNIX, MacOS etc.  In the BSD UNIX 
  2858. system, sockets are integrated in the system kernel while in the non-BSD 
  2859. systems, like OS/2, the socket services are provided in the form of libraries. 
  2860. This wide range of availability makes sockets one of the best portable network 
  2861. communication protocols. 
  2862.  
  2863. Description 
  2864.  
  2865. A socket is a peer to peer communications construct.  This construct basically 
  2866. consists of a name, or descriptor, and a network address.  There are a few 
  2867. different protocol families in which a socket can operate.  These include 
  2868. AF_INET, AF_UNIX, AF_PUP and AF_APPLETALK.  OS/2 currently only supports 
  2869. AF_INET.  This family designation is mainly used to define the addressing 
  2870. scheme which the socket will use. 
  2871.  
  2872. There are three types of sockets which OS/2 can use.  These are stream, 
  2873. datagram, and raw sockets.  Stream sockets interface with TCP, datagram sockets 
  2874. interface with UDP, and raw sockets interface with ICMP and IP.  The most 
  2875. commonly used socket type is the stream socket and this is what we will use in 
  2876. our sample programs. 
  2877.  
  2878. The stream socket is the most commonly used because of its reliability. Packets 
  2879. sent over a stream socket are guaranteed to be sent without error or 
  2880. duplication and they will be received in the same order they are sent in. There 
  2881. are no boundaries imposed on the data.  Think of the data as a simple stream of 
  2882. bytes flowing from one computer to another.  The only real bummer with stream 
  2883. sockets is that they are slower and require some extra programming overhead. 
  2884.  
  2885. NOTE:  Because there are no data boundaries, TCP does not know where a message 
  2886. ends or begins.  This means that if you send two packets to someplace you must 
  2887. have some way of letting they receiving end know how to delimit the two 
  2888. different packets.  Don't worry; it's a piece of cake. 
  2889.  
  2890. TCP/IP Internet Addressing 
  2891.  
  2892. The basic socket address consists of an internet address and a port address. 
  2893. The internet address is a 32 bit number that many of us are used to seeing as a 
  2894. series of four three digit numbers that are separated by decimals. This number 
  2895. is unique for every network interface within a domain.  For instance, I have 
  2896. two internet addresses on my computer at home.  One of the addresses is for my 
  2897. PPP connection and the other is for my Ethernet card. 
  2898.  
  2899. A port address is a 16 bit integer representing where the entry point for a 
  2900. particular service is on a server machine.  If you have TCP/IP installed, you 
  2901. can look in the \TCPIP\ETC\SERVICES file and see a long list of the most 
  2902. commonly used ports.  These are reserved and you should not set up any servers 
  2903. which use the ports for anything other than what the SERVICES file specifies. 
  2904.  
  2905. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  2906.  
  2907.  
  2908. ΓòÉΓòÉΓòÉ 10.2. The Socket API ΓòÉΓòÉΓòÉ
  2909.  
  2910. The Socket API 
  2911.  
  2912. The complete socket API consists of 58 different functions which can be broken 
  2913. down into 21 core functions and 37 utility functions.  Since there are so many 
  2914. I will only explain 10 of the core functions and then only the utility 
  2915. functions I need for this months programs.  As the series continues, I will use 
  2916. more functions and I'll be sure to explain them at that time. 
  2917.  
  2918. Socket Setup Functions 
  2919.  
  2920. These are the functions which are used by the client and server to set up the 
  2921. sockets on their respective ends. 
  2922.  
  2923. int sock_init()
  2924.  
  2925. Figure 1) sock_init() function 
  2926.  
  2927. The sock_init() call is used to initialize the socket data structures and check 
  2928. to see if INET.SYS is running.  Every program which uses sockets must use this 
  2929. call before doing any socket related activities.  The return values for this 
  2930. call are:    0 - Failure    1 - Success 
  2931.  
  2932. int socket(
  2933.    int   domain,  // This is the address type.  It must  always be  AF_INET
  2934.    int   type,    // This is the  type  of  socket created. SOCK_STREAM,
  2935.                   // SOCK_DGRAM, and SOCK_RAW are the possible choices
  2936.    int  protocol  // The protocol requested. Most commonly  0. Others are
  2937.                   // available.
  2938.    )
  2939.  
  2940. Figure 2) socket() function 
  2941.  
  2942. The purpose of the socket() function is to create a socket and return it 
  2943. descriptor.  It will return a non-negative integer if the function succeeds and 
  2944. will return -1 if an error occurs. 
  2945.  
  2946. int bind(
  2947.    int  s,                  // This is the socket to which an address is
  2948.                             // bound
  2949.    struct sockaddr *name,   // Pointer to the sockaddr structure containing
  2950.                             // the name to bind to socket s
  2951.    int  namelen             // Size of the buffer which  name points to in
  2952.                             // bytes
  2953.      )
  2954.  
  2955. Figure 3) bind() function 
  2956.  
  2957. bind() is used to bind a unique port number to a socket.  This is how a server 
  2958. uses a specific port for it's service.  The system can assign a port for you 
  2959. automatically but there is no way for clients wanting to connect to your server 
  2960. to know what that port is.  bind() will return 0 on success and -1 on failure. 
  2961.  
  2962. A Brief Aside.....The sockaddr structure 
  2963.  
  2964. The sockaddr structure, defined in <sys/socket.h>, is what it used to define a 
  2965. socket address.  It is defined as follows: 
  2966.  
  2967. struct sockaddr {
  2968.    ushort   sa_family,  // The address family which is always AF_INET for OS/2
  2969.    char  sa_data[14],   // 14 bytes of direct access data which is different
  2970.                         // for each family type
  2971.      }
  2972.  
  2973. Figure 4) sockaddr structure 
  2974.  
  2975. Because OS/2 only uses the AF_INET family, the sockaddr structure may be 
  2976. substituted with the sockaddr_in structure.  This is just a structure with the 
  2977. 14 data bytes defined for the internet addressing scheme.  It is defined in 
  2978. <netinet/in.h> header and looks like this: 
  2979.  
  2980. struct sockaddr_in {
  2981.    short sin_family;     // AF_INET always for OS/2
  2982.    ushort sin_port;      // Port to be used in network byte order
  2983.    struct in_addr sin_addr; // The internet address to be used. It is also in
  2984.                             // network byte order
  2985.    char sin_zero[8];     // Extra junk. Set it to all zeros
  2986.      }
  2987.  
  2988. Figure 5) sockadd_in structure 
  2989.  
  2990. Host and Network Byte Orders - Yet Another Brief Aside 
  2991.  
  2992. Machines on a network can have different ways of storing integers.  Intel 
  2993. machines, such as the PC we run OS/2 on, use "little endian", while Motorola 
  2994. and SPARC machines use "big endian".  Sockets require that all data coming in 
  2995. and going out be in network byte order, which is most significant byte first or 
  2996. "big endian".  There are a couple of socket utility functions used to convert 
  2997. integers from little to big endian and vise-versa.  The naming scheme for most 
  2998. of these functions makes it very easy to remember them so rather than listing 
  2999. all of the functions I will only explain the scheme. 
  3000.  
  3001. The function names are composed of 4 parts.  First is the byte order to 
  3002. translate from.  This is either n or h for network or host respectively. Second 
  3003. is just "to".  Third is the byte order to translate to.  This is also either n 
  3004. or h. Last is the type of integer being translated.  It will be l or s for a 
  3005. long or short integer.  The functions all return the same integer type as what 
  3006. they are converting.  For instance: 
  3007.  
  3008. To convert a port number to network byte order, which must be done for the port 
  3009. in the sockaddr_in structure, you would use the function htons(). 
  3010.  
  3011. There are also two functions which can be used to swap the bytes in an integer. 
  3012. These are bswap() and lswap() for short and long integer respectively.  All of 
  3013. these functions are defined in <utils.h>. 
  3014.  
  3015. Back to the socket API 
  3016.  
  3017. int soclose(
  3018.    int s     // Descriptor of the socket to be closed
  3019.    )
  3020.  
  3021. Figure 6) soclose() function 
  3022.  
  3023. The soclose() function is used to shut a socket down, free its resources, and 
  3024. close the TCP connection if one is open.  It will return 0 if successful and -1 
  3025. if it failed. 
  3026.  
  3027. Connection Management 
  3028.  
  3029. These functions are used by clients and server to initiate and manage socket 
  3030. connections from one another. 
  3031.  
  3032. int connect(
  3033.    int  s,        // The socket descriptor for your connection
  3034.    struct sockaddr *name,    // The socket address structure for the socket
  3035.                              // you wish to connect to
  3036.    int namelen    // Size, in bytes, of the socket address pointer to name
  3037.    )
  3038.  
  3039. Figure 7) connect() function 
  3040.  
  3041. connect() is one of the mainstay functions in a socket program.  You use it 
  3042. with a clients to connect between two machines on a network.  Connect will 
  3043. actually perform two tasks when it is called.  The first is to complete any 
  3044. binding necessary for a stream socket (in case you haven't already used bind() 
  3045. for this socket).  Second, It attempts to make the connection to the host 
  3046. supplied in the sockaddr structure. 
  3047.  
  3048. In order for connect() to succeed, the point to which it is attempting to 
  3049. connect must have a passive open socket pending.  In other words, the server 
  3050. had better be listening after calling bind() and listen().  If this is not the 
  3051. case, connect() will return a -1. 
  3052.  
  3053. Depending on how the socket you supply in s is configured, connect() will 
  3054. either block or not block.  Using our unmodified sockets for now, we will 
  3055. assume that connect() is always in blocking mode.  This means that while 
  3056. connect() is trying to connect the program or thread will not continue until a 
  3057. connection is established or an error is received.  I will cover the 
  3058. non-blocking situation in a future article. 
  3059.  
  3060. int listen(
  3061.    int s,         // Socket descriptor
  3062.    int backlog    // Number of pending connections allowed
  3063.    )
  3064.  
  3065. Figure 8) listen() function 
  3066.  
  3067. The listen() call applies only to stream sockets and performs two tasks. It 
  3068. will complete any binding if necessary (i.e.  you forgot to do it) and then it 
  3069. will create a connection request queue of length backlog.  After this queue is 
  3070. full, no further connections will be accepted. 
  3071.  
  3072. listen() is called when your server is ready to begin accepting connections 
  3073. from clients.  You must first allocate a stream socket using the socket() 
  3074. function then bind that socket to the socket address structure (or name) of the 
  3075. server.  Listen must be called before you can accept any connections. 
  3076.  
  3077. Backlog can be any number between 0 and SOMAXCONN.  SOMAXCONN is defined in 
  3078. <sys/socket.h>. 
  3079.  
  3080. int accept(
  3081.    int s,          // The socket for accepting new connections
  3082.    struct  sockaddr *name,   // Pointer to a buffer which will hold the name
  3083.                              // information for the connecting client
  3084.    int  *namelen   // Initially points to an integer which contains the size
  3085.                    // of the buffer name points to. On return, it contains
  3086.                    // the size of the struct name now points to
  3087.    )
  3088.  
  3089. Figure 9) accept() function 
  3090.  
  3091. accept() is what is used by a server to accept the incoming connection requests 
  3092. from a client.  The first connection request in the queue set up by listen() is 
  3093. the connection which is accepted.  A new socket will be created by accept() 
  3094. with the same properties as socket s. It is this socket which accept() will 
  3095. return.  If there are no pending connection requests then accept() will block 
  3096. until a request is made.  Non-blocking will be covered in a later article.  The 
  3097. new socket which is returned cannot be used to accept new connections; however, 
  3098. s is still available to accept more requests. 
  3099.  
  3100. The sockaddr structure in the parameter list is used to store the socket 
  3101. address structure of the connection requester.  This parameter can be NULL if 
  3102. you have no need for this information.  I find it handy to have this 
  3103. information so I advise you to go ahead and grab it even if you don't plan on 
  3104. using it.  If you do get lazy and set the name to NULL then you don't have to 
  3105. worry about the namelen parameter either. 
  3106.  
  3107. int shutdown(
  3108.    int s,   // Socket to be shutdown
  3109.    int how  // Method of shutdown
  3110.    )
  3111.  
  3112. Figure 10) shutdown() function 
  3113.  
  3114. shutdown() is used to shutdown all or part of a duplex connection.  In English, 
  3115. you can shutdown communication from socket s, to socket s, or both to and from 
  3116. socket s depending on the value of how.  Those values are 0, 1, and 2 
  3117. respectively. 
  3118.  
  3119. Connected Data Exchanges 
  3120.  
  3121. These functions are for transferring data to and from connected sockets. There 
  3122. are two more functions for receiving and sending data which I will cover later. 
  3123. They are a bit harder to handle than the two I have included here. 
  3124.  
  3125. int recv(
  3126.    int s,       // Socket to receive data from
  3127.    char   *buf, // Pointer to a buffer to receive  the data into
  3128.    int  len,    // Length of buffer pointed to by  buf  in bytes
  3129.    int flags    // Flags for receiving the data
  3130.    )
  3131.  
  3132. Figure 11) recv() function 
  3133.  
  3134. recv() is used to receive data from a connected socket.  If successful it will 
  3135. return the length, in bytes, of the message packet.  A value of 0 indicates the 
  3136. connection is closed and -1 indicates an error. 
  3137.  
  3138. recv() will block, if the socket is in blocking mode, until a message arrives 
  3139. and then places the incoming data into the buffer and returns its length.  If 
  3140. the incoming data is too large to fit into the buffer than the socket will read 
  3141. up to the parameter specified in len.  There is a method to check and see the 
  3142. amount of data waiting to be read but it is part an advanced topic I don't want 
  3143. to sling at you right now. 
  3144.  
  3145. There are two parameters you can ''OR" together to modify how recv() reads the 
  3146. incoming data.  The first, MSG_OOB, is for datagram socket and will not be 
  3147. covered.  The other is MSG_PEEK.  This flag allows you 'peek' at the data 
  3148. without consuming it.  This means the data is still waiting to be fully read in 
  3149. from the socket.  Normally, NULL is used in this parameter. 
  3150.  
  3151. int send(
  3152.    int s,     // Socket to send data on
  3153.    char *msg, // Pointer to a buffer containing  data to be sent
  3154.    int   len, // Size, in bytes, of data which msg points to
  3155.    int flags  // Flags for sending data
  3156.    )
  3157.  
  3158. Figure 12) send() function 
  3159.  
  3160. send() is recv()'s counterpart.  It operates in the same manner as recv() 
  3161. except it sends the data through the socket.  send() will send all of the data 
  3162. in msg as long as it doesn't exceed the total socket buffer space.  If is 
  3163. exceeds this buffer size then send will block until all of the data can be 
  3164. sent.  This will only occur if you send a large amount of data rapidly through 
  3165. the socket. 
  3166.  
  3167. Both of the flags which can be set for send() are not normally used; therefore, 
  3168. I will skip them.  Use a 0 in the flag parameter when using this function call. 
  3169.  
  3170. This wraps up the discussion on what I feel are the minimal functions needed to 
  3171. set up a very basic client and server.  At this point you should have a basic 
  3172. understanding of how to program a sockets based application. 
  3173.  
  3174. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3175.  
  3176.  
  3177. ΓòÉΓòÉΓòÉ 10.3. Finish Up and Next Month ΓòÉΓòÉΓòÉ
  3178.  
  3179. Finish Up and Next Month 
  3180.  
  3181. I hope this article will help you to get started in programming with sockets. 
  3182. It may seem like there is a lot of information needed to program with sockets; 
  3183. however, once this slightly steep learning curve is past it becomes second 
  3184. nature to program sockets quickly and easily. 
  3185.  
  3186. Next month I will be adding more features to the simple client/server program 
  3187. and discuss more of the socket utility API.  Until then I urge you to read over 
  3188. my sample code and play with the two programs to get a good feel of how they 
  3189. are working.  Thanks for reading..  See you next month! 
  3190.  
  3191. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3192.  
  3193.  
  3194. ΓòÉΓòÉΓòÉ 11. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
  3195.  
  3196. /dev/EDM/BookReview 
  3197.  
  3198. Written by Carsten Whimster 
  3199.  
  3200. Introduction 
  3201.  
  3202. In /dev/EDM2/BookReview, I focus on development books and materials.  The 
  3203. column is written from the point of view of an intermediate PM C programmer and 
  3204. intermediate REXX programmer.  Pick up whichever book strikes your fancy, and 
  3205. join the growing group of people following our PM programming columns.  I have 
  3206. already reviewed a number of beginner's books, and will try to concentrate a 
  3207. bit more on intermediate techniques and special topics from now on. 
  3208.  
  3209. Please send me your comments and thoughts so that I can make this column as 
  3210. good as possible.  I read and respond to all mail. 
  3211.  
  3212. Designing High-Powered OS/2 Warp Applications is an updated version of David 
  3213. Reich's earlier Designing OS/2 Applications, and contains some expanded 
  3214. sections, and new PowerPC consideration sections. 
  3215.  
  3216. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3217.  
  3218.  
  3219. ΓòÉΓòÉΓòÉ 11.1. Errata ΓòÉΓòÉΓòÉ
  3220.  
  3221. Errata 
  3222.  
  3223. My Web page is continually growing, and has become quite large and popular. It 
  3224. has recently had over 1500 hits, forcing me to expand my counter to 5 digits. 
  3225. It should be ok there for a while [grin].  It includes, among other things, a 
  3226. short list of developer-oriented links.  Check it out at 
  3227. http://www.undergrad.math.uwaterloo.ca/~bcrwhims/os2.html. 
  3228.  
  3229. This summer has seen me incorporating a number of useful changes into my 
  3230. POV-Panel/2, culminating in a 1.1 beta release available on my Web page.  It 
  3231. also saw me getting my first few registrations, so I must be finally doing 
  3232. something right [grin].  I had a lot of learning to do during this, however, 
  3233. both with respect to REXX, VX-REXX, OS/2, and supporting paying customers.  It 
  3234. seems that if you pass a commandline to REXX with a quoted long filename in it, 
  3235. it isn't parsed correctly, but rather on a word-by-word basis.  In some ways 
  3236. this is not too strange, but it is rather awkward, and has caused me to create 
  3237. a known-bugs section in my README file for the program. 
  3238.  
  3239. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3240.  
  3241.  
  3242. ΓòÉΓòÉΓòÉ 11.2. Designing High-Powered OS/2 Warp Applications ΓòÉΓòÉΓòÉ
  3243.  
  3244. Designing High-Powered OS/2 Warp Applications 
  3245.  
  3246. Designing High-Powered OS/2 Warp Applications is a unique type of book.  It 
  3247. does not attempt to teach you how to program, but rather how to design 
  3248. programs, or how to think about programming.  These are the chapter titles: 
  3249.  
  3250.       Section I. Why OS/2? 
  3251.       1.  OS/2 as an End-User Platform 
  3252.       2.  Why Program for OS/2? 
  3253.       3.  OS/2 as a Development Platform 
  3254.       Section II.  Overall Application Design 
  3255.       4.  Good Programs Have Good Up-Front Design 
  3256.       5.  OS/2 Kernel Architecture 
  3257.       6.  Presentation Manager, Graphics, and the User Interface 
  3258.       7.  OS/2 Warp for the PowerPC 
  3259.       8.  Features for Your Application 
  3260.       9.  Application Structure 
  3261.       Section III.  Use Building Blocks or Your App Will Crumble 
  3262.       10.  Block Design and Architecture 
  3263.       11.  Designing the User Interface 
  3264.       12.  Where's the Beef? 
  3265.       Section IV.  Making It Happen 
  3266.       13.  The Development Environment 
  3267.       14.  Prototyping the User Interface 
  3268.       15.  Building the Core Functions 
  3269.       16.  Using Advanced Functions 
  3270.       17.  Non-English-Language Support 
  3271.       Section V. Performance 
  3272.       18.  Base Tuning 
  3273.       19.  Visual Tuning 
  3274.       Section VI.  Testing and Code Changes 
  3275.       20.  Testing Methodology 
  3276.       21.  Code Change 
  3277.       Section VII.  Installation Programs 
  3278.       22.  Designing the Installation Program 
  3279.       23.  Appendix A:  Summary and Conclusions 
  3280.       24.  Appendix B:  Bibliography 
  3281.  
  3282.  I will concentrate on the sections, rather than the chapters, since the 
  3283.  divisions between the chapters are much fuzzier than in actual programming 
  3284.  books. 
  3285.  
  3286.  If any of the above sounds familiar, that is because it is.  I didn't realize 
  3287.  until I started reading (and after getting a heavy dose of deja-vu all over 
  3288.  again [grin]) that this book is an update of Reich's previous Designing OS/2 
  3289.  Applications.  It has one new chapter, a few new sections, and some updated 
  3290.  text here and there.  For this reason (after much internal debating), I have 
  3291.  decided to just concentrate on the new or changed sections, and a few problem 
  3292.  areas in the older book (to see if they have been fixed), rather than copying 
  3293.  the old review, or pretending that it never happened, and reviewing it as if 
  3294.  it was totally or even mostly new.  I will use some of the text from the 
  3295.  previous review, and just brush quickly through a lot of the book, but really 
  3296.  concentrate on the new stuff.  For a complete review of the previous book, I 
  3297.  refer the reader to Volume 3 Issue 1 of EDM/2, available at fine FTP sites 
  3298.  near you.  Here goes... 
  3299.  
  3300.  Section I explains the advantages of OS/2 over other platforms.  This is 
  3301.  explained both from an end-user's point of view, as well as from the 
  3302.  programmer's point of view, and includes discussion of such issues as 
  3303.  pre-emptive multitasking, multi-threading, virtual memory, and so on.  There 
  3304.  are new sub-sections on symmetric multiprocessing and portability to the 
  3305.  PowerPC.  The importance of the proper use of threads to benefit from SMP is 
  3306.  stressed.  The PowerPC sub- section has a small quote which re-raises an old 
  3307.  point of discussion between followers of the PowerPC:  "Object code compiled 
  3308.  for Intel chips will not run on most PowerPC RISC chips."  The key word here 
  3309.  is, of course, "most".  IBM has repeatedly denied (until I last heard) that 
  3310.  there is a PowerPC chip being designed which has hardware emulation of the 
  3311.  80x86 instruction set to speed up running Intel-compiled programs, and to 
  3312.  speed up the acceptance of the PowerPC chip.  Considering Reich's insider 
  3313.  position (he does not work for IBM any more, but was on the OS/2 development 
  3314.  team, and has very strong ties in IBM), I would take this as further evidence 
  3315.  that such a chip is actually being designed.  Interesting. 
  3316.  
  3317.  Reich also has a small dig against Microsoft in the following sentence, which 
  3318.  is quite amusing:  "In contrast to others, with sets and subsets of APIs, this 
  3319.  gives your user the consistency without you having to rewrite code to exploit 
  3320.  the set or subset of function depending on which version of the operating 
  3321.  system you may be on."  Apart from the obvious value in advocacy USENET 
  3322.  forums, this is quite interesting from a programmer's point of view too, in 
  3323.  that we have it so much easier over here than they do over there with their 
  3324.  ever-changing APIs.  The basic message here is that only a recompile is 
  3325.  necessary to move to the PowerPC, except for device-driver writers. 
  3326.  
  3327.  The next new sub-section is on "OS/2 Development:  The Next Generation".  Huh, 
  3328.  Star Trek?  Nope, just a brief paragraph extolling the virtues of objects, 
  3329.  code and object reuse, and development environments. Curiously enough, IBM's 
  3330.  latest CSet++ (Now Visual Age C++) is much more of an "environment" than it 
  3331.  ever was, so Reich is obviously in tune with the developments at IBM [grin]. 
  3332.  
  3333.  Section II is a large section, which outlines the overall application design 
  3334.  theory and procedures.  The importance of good, solid, up-front design are 
  3335.  stressed over and over again, not quite ad nauseam.  Again, there is a new 
  3336.  sub- section on SMP, which discusses scheduling on SMP machines.  It is 
  3337.  obviously (but not obviously enough!)  very important not to make assumptions 
  3338.  based on the fact that on the vast majority of machines, only one thread can 
  3339.  run at a time.  This does happen, though, and it is a very subtle thing, so 
  3340.  making sure that your design is correct up-front really pays off here. 
  3341.  Timing-related bugs are a beast to debug, as I found out in CS342 (concurrent 
  3342.  programming), but that is another story.  He also emphasizes that just adding 
  3343.  more threads to make a program SMP-able is not a good idea; rather, add 
  3344.  threads where appropriate on non-SMP machines, and SMP will enhance the 
  3345.  running of your program. 
  3346.  
  3347.  Chapter 7 is a completely new chapter on Warp for the PowerPC.  As such, I 
  3348.  will go into more detail here.  The Workplace OS is explained, and the fact 
  3349.  that OS/2 Warp for the PowerPC is merely the first implementation of this is 
  3350.  stated.  The personalities of Workplace OS are explained.  Basically they are 
  3351.  just an API layer between the program and the IBM Microkernel, which is a 
  3352.  Mach-derivative.  This API layer can be almost anything, including OS/2 PM, 
  3353.  DOS (an INT13 etc.  API layer?  Yuck), AIX, and at some point in the not too 
  3354.  distant past, Windows NT and System 7. Understandably, both Apple and 
  3355.  Microsoft got cold feet about having their OSes run under an IBM OS, and 
  3356.  canned the idea.  Anyway, the main (and startling) difference between 
  3357.  Workplace OS and Intel OS/2 is that the device drivers, OS/2 API, and other 
  3358.  sub-personalities run as user programs, not as privileged programs!  This 
  3359.  makes no difference to most of us, with the glaring exception of device-driver 
  3360.  writers.  It does mean, though, that once the microkernel is stable and 
  3361.  mature, this baby will be solid as a rock, and re-booting will become very 
  3362.  rare.  As a worst-case scenario, you will have to restart the interface.  This 
  3363.  we can already do now, but not in quite the same way.  Device driver writers 
  3364.  can look forward to much more portable drivers, since they are not, to any 
  3365.  large extent, hardware dependent, but rather send messages to and from the 
  3366.  microkernel.  At least, this is the way it is explained, although it seems a 
  3367.  little hard to believe; only a recompile should be necessary.  I don't quite 
  3368.  see where the new code goes every time a new sound card or video card is 
  3369.  written; in the microkernel?  A new microkernel every time a new "thing" is 
  3370.  released?  Inconceivable.  To some extent then, these device drivers must be 
  3371.  hardware dependent, but only dependent on the "thing", not the machine.  Weird 
  3372.  science.  Same device driver works for all the personalities too.  This is 
  3373.  easier to see.  Basically, each personality is comprised of a server, and a 
  3374.  client-library (the API).  The server has the major chunks of ideology 
  3375.  specific to the O/S it emulates, and the client-library actually services the 
  3376.  API calls from programs, sometimes without calling the server, other times by 
  3377.  calling the server.  All calls take the form of messages, which are more or 
  3378.  less the same old thing for PM writers, except on a below- the-surface scale. 
  3379.  
  3380.  Section III discusses modularization in much greater detail.  Reich presents 
  3381.  his idea of design (which is tempered by years of writing for OS/2, so listen 
  3382.  up), starting with the overall design accomplished by taking a black-box 
  3383.  approach to your app.  There is a new sub-section on Application Development 
  3384.  Tools for OS/2 (actually this used to be a CASE tools section, but CASE tools 
  3385.  are frequently way too expensive for individual developers, so I imagine that 
  3386.  is why the section now has a more generic flavour) which discusses the various 
  3387.  types of tools that are available to help design and write applications, 
  3388.  including RAD environments, CASE tools, and so on.  This is followed by a 
  3389.  sub-section on Object Technologies.  SOM, CORBA, and OpenDoc are discussed 
  3390.  here, along with explanations of how it all hangs together. Finally, there is 
  3391.  a new sub-section on Interprocess Objects and Agents, which discusses 
  3392.  communication with WPS objects.  DSOM is also briefly mentioned. 
  3393.  
  3394.  Making it Happen is the title of section IV.  Practical decisions are the main 
  3395.  focus here, such as the choice of development environment, tools, source code 
  3396.  revision systems, and so on.  The sub-section Handling Long Jobs has been 
  3397.  restructured a little to make the flow more logical, and this has affected the 
  3398.  layout of the next couple of sections.  In the next chapter, there is a new 
  3399.  sub-section named Guard Pages and Exceptions which discusses, well, I won't 
  3400.  spoil the surprise [grin]. 
  3401.  
  3402.  Note:  the example on semaphores and deadlock is strictly speaking inaccurate. 
  3403.  I quote:  "You can see there are three threads.  Threads 1 and 2 make use of 
  3404.  semaphore A. Threads 2 and 3 make use of semaphore B, and threads 1 and 3 make 
  3405.  use of semaphore C. No two threads make use of the same resources, but you can 
  3406.  see that if thread 1 has semaphore A, thread 2 has semaphore B, and thread 3 
  3407.  has semaphore C, any semaphore request by any of the three will cause a 
  3408.  deadlock."  In fact, if, say, thread 1 requests semaphore C, it is still 
  3409.  possible for the three threads to complete as follows: thread 1 requests 
  3410.  semaphore C, and locks.  Thread 2 requests semaphore A, and locks.  Thread 3 
  3411.  finishes with semaphore C, releases it, requests semaphore B, and locks. 
  3412.  Thread 1 can now get semaphore C, and run to completion, releasing semaphore A 
  3413.  and C. Now thread 2 can get semaphore A, and run to completion, releasing 
  3414.  semaphore A and B. Finally, thread 3 gets semaphore B, and runs to completion. 
  3415.  In fact, any sequence of events will complete, which has one thread giving up 
  3416.  a semaphore before requesting another.  If all three threads needed two 
  3417.  semaphores at the same time, and each acquired one, then any further requests 
  3418.  causes deadlock.  This is slightly different than the statement of the 
  3419.  problem, but it is significant.  I imagine this is what was meant.  This 
  3420.  section needed rewording in the first book too, so I guess Reich doesn't read 
  3421.  my column.  (Sigh) 
  3422.  
  3423.  There is a small new sub-section (which isolates material covered elsewhere in 
  3424.  the previous book, I think) which discusses resources in DLLs. 
  3425.  
  3426.  Section V deals with performance tuning.  Many little neat performance tricks 
  3427.  are presented, such as minimizing fix-up costs, accessing DLLs intelligently, 
  3428.  thread priorities, EXE packing, and DLL placement.  User interface speed is 
  3429.  also discussed in some detail.  There is a new sub-section called Code Size 
  3430.  versus Path, which should be called Code Size versus Path Length, I think. 
  3431.  Basically, Reich advises that, since CPU power is getting cheaper much faster 
  3432.  than RAM and hard drives, and since the CPU is faster than either, it is 
  3433.  advisable to pack code and data as much as possible, and to unpack it using 
  3434.  extra CPU cycles.  There is a limitation to this, of course, but in general I 
  3435.  would agree.  One extreme example of the benefits of this is given by Stacker 
  3436.  and similar programs:  occasionally, having the data compressed on the 
  3437.  hard-drive, and decompressing it on-the-fly actually yields an increase in 
  3438.  speed, due to the reduced wait for the hard-drive to transfer the data!  This 
  3439.  is not in all cases, of course, but more often that you would think. 
  3440.  
  3441.  The penultimate section deals with testing and changing code.  These two 
  3442.  chapters are short, sweet, use common sense, and haven't changed, so I will 
  3443.  leave them out here. 
  3444.  
  3445.  The final section is on installation programs, and this happens to be a pet 
  3446.  peeve of mine.  Frequently, you pick up some really neat program, but get 
  3447.  frustrated trying to install it correctly.  In my opinion, a decent 
  3448.  installation procedure should include instructions on how to install manually, 
  3449.  in case the installation program fails.  This is obviously difficult to do in 
  3450.  the case of something as complex as OS/2 itself.  With the types of programs 
  3451.  that most of us write, however, it should be a breeze.  In addition, 
  3452.  reinstalling and uninstalling are mentioned, but too briefly.  Uninstallation 
  3453.  programs really should be given more emphasis, especially in this day and age 
  3454.  where programs like Uninstaller for Windows are perpetually at or near the top 
  3455.  of the best-seller list, and Windows 95's logo program requires an 
  3456.  uninstallation program. 
  3457.  
  3458.  There is a brief summary following this last section, which concludes the 
  3459.  book. 
  3460.  
  3461.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3462.  
  3463.  
  3464. ΓòÉΓòÉΓòÉ 11.3. Summary ΓòÉΓòÉΓòÉ
  3465.  
  3466. Summary 
  3467.  
  3468. Not surprisingly, this book is very much like its predecessor.  In fact, so 
  3469. little has changed that it is more of an update than a new book.  A few areas 
  3470. have been improved, and a few need improvement, but overall this book has 
  3471. retained the strengths of the previous book, and still should have a spot in 
  3472. most OS/2 programmers' libraries. 
  3473.  
  3474. The book is now pretty up to date, which is a plus, but the semaphore example 
  3475. still needs rewording, and the book still drags slightly in the early chapters. 
  3476. The book still has a slight C bias, which I suppose is in order, despite going 
  3477. a little against the self-imposed language-neutrality of the text. 
  3478.  
  3479. If you already have the previous book, then take a long hard look at the new 
  3480. sections, and see if you really need it.  If you don't, get it; 'nuff said.  It 
  3481. is a very good book for showing you what features OS/2 offers a programmer, and 
  3482. how to go about the up-front design of applications.  For large projects, this 
  3483. kind of book is essential.  It gets a solid A on the report card. 
  3484.  
  3485. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3486.  
  3487.  
  3488. ΓòÉΓòÉΓòÉ 11.4. Book Reviewed ΓòÉΓòÉΓòÉ
  3489.  
  3490. Book Reviewed 
  3491.  
  3492.      Designing High-Powered OS/2 Warp Applications, Reich 
  3493.         -  John Wiley and Sons. ISBN 0-471-11586-X. US$34.95, CAN$50. 
  3494.         -  OS/2 Programmers 
  3495.         -  A 
  3496.      This book is a rewrite of Reich's earlier Designing OS/2 Applications, 
  3497.       and has been updated to include PowerPC and SMP information.  A very 
  3498.       thorough book on the how-tos of designing applications, rather than 
  3499.       actually writing them. Recommended strongly for anyone starting large 
  3500.       projects. 
  3501.  
  3502.  NOTES 
  3503.  
  3504.  Please note that books aimed at different audiences should only be compared 
  3505.  with great care, if at all.  I intend to concentrate on the strong points of 
  3506.  the books I review, but I will point out any weaknesses in a constructive 
  3507.  manner. 
  3508.  
  3509.  LEGEND 
  3510.  
  3511.  BOOK:  The name of the book, and the author(s) 
  3512.  
  3513.  PUBLISHING INFORMATION:  Publishing company, ISBN, and approximate price. 
  3514.  
  3515.  AUDIENCE:  This is a description of the audience I think the book targets 
  3516.  best.  This is not intended as gospel, just a guideline for people not 
  3517.  familiar with the book. 
  3518.  
  3519.  MARK:  My opinion of the success of the book's presentation, and how well it 
  3520.  targets its audience.  Technical content, accuracy, organization, readability, 
  3521.  and quality of index all weigh heavily here, but the single most important 
  3522.  item is how well the book covers what it says it covers.  Many books try to 
  3523.  cover too much, and get a lower mark as a result. 
  3524.  
  3525.  A+   Ground-breaking, all-around outstanding book 
  3526.  A    Excellent book.  This is what I want to see happen a lot 
  3527.  A-   Excellent book with minor flaws 
  3528.  B+   Very good book with minor flaws or omissions 
  3529.  B    Good book with some flaws and omissions 
  3530.  B-   Good book, but in need of improvement 
  3531.  C+   Mediocre book with some potential, but in need of some updating 
  3532.  C    Mediocre book with some good sections, but badly in need of fixing 
  3533.  C-   Mediocre book, little good material, desperately in need of an overhaul 
  3534.  D    Don't buy this book unless you need it, and nothing else exists 
  3535.  F    Don't buy this book.  Period 
  3536.  
  3537.  COMMENTS:  This is a very brief summary of the review proper. 
  3538.  
  3539.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3540.  
  3541.  
  3542. ΓòÉΓòÉΓòÉ 11.5. Index ΓòÉΓòÉΓòÉ
  3543.  
  3544. Index 
  3545.  
  3546. This Content Index is designed to let you find the book that covers the topics 
  3547. you need to learn about.  It will eventually have a lot of categories, with 
  3548. each book being rated along each row.  These tables will be quite large, and 
  3549. will continually grow, so please give me your feedback regarding what 
  3550. categories you would like to see, and which you don't.  It may take me a while 
  3551. to flesh them out, so have a little patience. 
  3552.  
  3553. Book Legend 
  3554.  
  3555. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3556. ΓöéCode ΓöéIssue  ΓöéTitle                                                              Γöé
  3557. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3558. ΓöéRWP  Γöé2-3    ΓöéReal World Programming for OS/2 2.1                                Γöé
  3559. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3560. ΓöéLPE  Γöé2-4    ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example       Γöé
  3561. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3562. ΓöéODD  Γöé2-5    ΓöéWriting OS/2 2.1 Device Drivers in C                               Γöé
  3563. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3564. ΓöéGPI  Γöé2-6    ΓöéOS/2 Presentation Manager GPI                                      Γöé
  3565. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3566. ΓöéTAO  Γöé2-7    ΓöéThe Art of OS/2 2.1 C Programming                                  Γöé
  3567. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3568. ΓöéMOR  Γöé2-8    ΓöéMastering OS/2 REXX                                                Γöé
  3569. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3570. ΓöéRSH  Γöé2-9    ΓöéREXX Reference Summary Handbook                                    Γöé
  3571. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3572. ΓöéADO  Γöé2-10   ΓöéApplication Development Using OS/2 REXX                            Γöé
  3573. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3574. ΓöéPMP  Γöé2-11   ΓöéOS/2 Presentation Manager Programming                              Γöé
  3575. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3576. ΓöéDOA  Γöé3-1    ΓöéDesigning OS/2 Applications                                        Γöé
  3577. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3578. ΓöéOSP  Γöé3-2    ΓöéOS/2 Programming                                                   Γöé
  3579. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3580. ΓöéTGO  Γöé3-4    ΓöéThe GUI-OOUI War                                                   Γöé
  3581. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3582. ΓöéOU   Γöé3-5    ΓöéOS/2 Warp Unleashed, Deluxe Edition                                Γöé
  3583. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3584. ΓöéQR1  Γöé3-6    ΓöéWIN Functions, OS/2 Quick Reference Library Volume 1               Γöé
  3585. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3586. ΓöéPWG  Γöé3-7    ΓöéProgramming the OS/2 Warp Version 3 GPI                            Γöé
  3587. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3588. ΓöéDHP  Γöé3-8    ΓöéDesigning High-Powered OS/2 Warp Applications                      Γöé
  3589. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3590.  
  3591. NOTE:  Books which cover the same material can look similar in this table, but 
  3592. be different in real life.  The style of a book, for example, can not be seen 
  3593. from a quick table, so make sure that you follow up by reading the reviews of 
  3594. the books you find here.  Finally, be sure that the books you are comparing are 
  3595. aimed at the same audiences. 
  3596.  
  3597. PM C Books 
  3598.  
  3599. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3600. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéGPI    ΓöéFonts  ΓöéPrint  Γöé
  3601. Γöé     Γöé     ΓöéBasics ΓöéDriversΓöéAVIO   Γöé       Γöé       Γöé       Γöé       Γöé
  3602. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3603. ΓöéRWP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé4      Γöé4      Γöé4      Γöé3      Γöé
  3604. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3605. ΓöéPME  ΓöéB-   Γöé1      Γöé0      Γöé0      Γöé2      Γöé2      Γöé2      Γöé0      Γöé
  3606. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3607. ΓöéODD  ΓöéA    Γöé0      Γöé5      Γöé0      Γöé0      Γöé1      Γöé0      Γöé1      Γöé
  3608. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3609. ΓöéGPI  ΓöéC+   Γöé0      Γöé0      Γöé0      Γöé0      Γöé5      Γöé2      Γöé3      Γöé
  3610. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3611. ΓöéTAO  ΓöéB+   Γöé3      Γöé2      Γöé1      Γöé4      Γöé1      Γöé2      Γöé0      Γöé
  3612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3613. ΓöéPMP  ΓöéA-   Γöé1      Γöé0      Γöé1      Γöé5      Γöé3      Γöé4      Γöé2      Γöé
  3614. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3615. ΓöéOSP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé3      Γöé2      Γöé1      Γöé0      Γöé
  3616. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3617. ΓöéQR1  ΓöéA    Γöé0      Γöé0      Γöé0      Γöé5 (WIN)Γöé0      Γöé0      Γöé0      Γöé
  3618. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3619. ΓöéPWG  ΓöéA-   Γöé0      Γöé0      Γöé0      Γöé1      Γöé5      Γöé5      Γöé5      Γöé
  3620. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3621.  
  3622. REXX Books 
  3623.  
  3624. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3625. ΓöéBOOK ΓöéMARK ΓöéREXX     ΓöéWPS      ΓöéReferenceΓöé
  3626. Γöé     Γöé     ΓöéIntro    Γöé         Γöé         Γöé
  3627. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3628. ΓöéMOR  ΓöéB    Γöé4        Γöé0        Γöé2        Γöé
  3629. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3630. ΓöéRSH  ΓöéA    Γöé1        Γöé2        Γöé5        Γöé
  3631. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3632. ΓöéADO  ΓöéA-   Γöé3        Γöé2        Γöé4        Γöé
  3633. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3634.  
  3635. System and Non-Programming Books 
  3636.  
  3637. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3638. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéThreadsΓöéGPI    ΓöéFonts  ΓöéPrint  ΓöéWPS    Γöé
  3639. Γöé     Γöé     ΓöéBasics ΓöéDriversΓöéAVIO   Γöé       Γöé       Γöé       Γöé       Γöé       Γöé       Γöé
  3640. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3641. ΓöéDOA  ΓöéA    Γöé4      Γöé4      Γöé2      Γöé4      Γöé5      Γöé3      Γöé2      Γöé3      Γöé1      Γöé
  3642. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3643. ΓöéTGO  ΓöéB    Γöé0      Γöé0      Γöé0      Γöé2      Γöé1      Γöé0      Γöé2      Γöé1      Γöé5      Γöé
  3644. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3645. ΓöéOU   ΓöéA+   Γöé1      Γöé4      Γöé4      Γöé5      Γöé2      Γöé5      Γöé5      Γöé5      Γöé5      Γöé
  3646. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3647. ΓöéDHP  ΓöéA    Γöé4      Γöé4      Γöé2      Γöé4      Γöé5      Γöé3      Γöé2      Γöé3      Γöé1      Γöé
  3648. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3649.  
  3650. Ratings Legend 
  3651.  
  3652.  Rating         Description 
  3653.  0              No coverage 
  3654.  1              Very light coverage 
  3655.  2              Introductory coverage 
  3656.  3              Good Coverage 
  3657.  4              In-depth coverage 
  3658.  5              Authoritative 
  3659.  
  3660.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3661.  
  3662.  
  3663. ΓòÉΓòÉΓòÉ 11.6. Coming Up ΓòÉΓòÉΓòÉ
  3664.  
  3665. Coming Up 
  3666.  
  3667. I have here a trilogy of Warp API reference manuals, which I will review for 
  3668. next month.  Other books I would like to review are: 
  3669.  
  3670.      OS/2 Warp (Control Program/Workplace Shell/Presentation Manager) API, 
  3671.       Stock, Pollack, Barnum 
  3672.      OS/2 Presentation Manager GPI, 2nd edition, Winn 
  3673.      The Design of OS/2, 2nd Edititon, Kogan and Deitel 
  3674.  
  3675.  I am also toying with the idea of reviewing OS/2 Certification Handbook. While 
  3676.  it is not a programmer's book, it can be very relevant to programmers who are 
  3677.  faced with having to support their programs in the real world, and in fact, 
  3678.  this very situation was a large factor in making me purchase this book. 
  3679.  
  3680.  If anyone has a book they want to see reviewed, I will be happy to oblige. 
  3681.  Just mail me and tell me.  Publishers can send me books at the address on my 
  3682.  personal page at the end of the magazine, and I will review all OS/2 
  3683.  development- related and advanced user books I receive. 
  3684.  
  3685.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3686.  
  3687.  
  3688. ΓòÉΓòÉΓòÉ 12. Introduction to PM Programming ΓòÉΓòÉΓòÉ
  3689.  
  3690. Introduction to PM Programming 
  3691.  
  3692. Written by Larry Salomon Jr. 
  3693.  
  3694. Introduction 
  3695.  
  3696. The purpose of this column is to provide the readers out there who are not 
  3697. familiar with PM application development the information necessary to satisfy 
  3698. their curiosity, educate themselves, and give them an advantage over the 
  3699. documentation supplied by IBM.  Of course, much of this stuff could probably be 
  3700. found in one of the many books out there, but the problem with books in general 
  3701. is that they don't answer the questions you have after you read the book the 
  3702. first time through. 
  3703.  
  3704. I will gladly entertain feedback from the readers about what was `glossed over' 
  3705. or what was detailed well, what tangential topics need to be covered and what 
  3706. superfluous crap should have been removed.  This feedback is essential in 
  3707. guaranteeing that you get what you pay for.  <grin> 
  3708.  
  3709. It should be said that you must not depend solely on this column to teach you 
  3710. how to develop PM applications; instead, this should be viewed as a supplement 
  3711. to your other information storehouses (books, the network conferences, etc.). 
  3712. Because this column must take a general approach, there will be some topics 
  3713. that you would like to see discussed that really do not belong here.  Specific 
  3714. questions can be directed to me via email and I will do my best to answer them 
  3715. in a timely fashion. 
  3716.  
  3717. This month 
  3718.  
  3719. This month, we will finish up our tour of the menu window class by looking at 
  3720. how popup menus are implemented, more of the messages that are used for 
  3721. interacting with the menu control, and one or two other neat things that can be 
  3722. done with menus. 
  3723.  
  3724. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3725.  
  3726.  
  3727. ΓòÉΓòÉΓòÉ 12.1. Popup Menus ΓòÉΓòÉΓòÉ
  3728.  
  3729. Popup Menus 
  3730.  
  3731. I can remember when my colleague at IBM, Thierry Samama, wrote a program called 
  3732. UBU, which sported a popup menu to avoid using real estate which was quite 
  3733. precious.  These behaved much like their modern counterparts and I wouldn't be 
  3734. surprised to find that IBM's CUA group lifted the concept from this program 
  3735. which was developed when OS/2 1.2 was the current product level. 
  3736.  
  3737. Figure 1) Simple popup menu 
  3738.  
  3739. From a user's perspective, popup menus are requested by pressing some 
  3740. combination of mouse buttons or (since CUA requires that all functions are 
  3741. accessible by mouse and keyboard) keystrokes.  The user likes popup menus 
  3742. because they do not take up screen space that could be used for the workarea(s) 
  3743. and because they can be made context-sensitive (which is a fancy word to mean 
  3744. that only menuitems that are valid for the object(s) under the location of the 
  3745. mouse are displayed). 
  3746.  
  3747. From a developer's perspective, popup menu requests are sent as a single 
  3748. message to the control under the mouse.  It is the task of the window procedure 
  3749. associated with the control to determine what to do - if anything - with the 
  3750. request.  The programmer hates popup menus because they create more work for 
  3751. them.  However, the results are very nice, so the extra effort is worth it (in 
  3752. my opinion). 
  3753.  
  3754. With the exception of the container control (WC_CONTAINER), the standard window 
  3755. classes ignore the popup menu request.  Thus, you will have to subclass the 
  3756. controls where you want to receive this message.  Once you receive the message, 
  3757. the remainder of the processing is trivial - there is only one function call to 
  3758. be added and the WM_COMMAND message processing remains unchanged. 
  3759.  
  3760. The popup menu request message is WM_CONTEXTMENU.  The system fortunately 
  3761. handles both the mouse and keyboard combinations for you and also uses the 
  3762. current settings in the `Mappings' tab of the Mouse settings notebook. 
  3763.  
  3764. WM_CONTEXTMENU 
  3765.  
  3766.      SHORT1FROMMP(mpParm1) - x position of the mouse in window coordinates 
  3767.      SHORT2FROMMP(mpParm2) - y position of the mouse in window coordinates 
  3768.      SHORT1FROMMP(mpParm1) - reserved 
  3769.      SHORT2FROMMP(mpParm2) - TRUE if the keyboard was used, FALSE otherwise 
  3770.      SHORT1FROMMR(mrResult) - TRUE if the message was processed 
  3771.  
  3772.  Remember, window coordinates are relative to the lower left corner of the 
  3773.  window to which they are associated.  This isn't what we want, as we'll see 
  3774.  below. 
  3775.  
  3776.  Once you receive the message and have decided to display a popup menu, you 
  3777.  will call the function WinPopupMenu() to perform all of the work. It will 
  3778.  convert the menu from horizontal to vertical format and will display the menu 
  3779.  at the specified location. 
  3780.  
  3781.   BOOL WinPopupMenu(hwndParent,
  3782.                     hwndOwner,
  3783.                     hwndMenu,
  3784.                     ulX,
  3785.                     ulY,
  3786.                     ulItem,
  3787.                     ulFlags);
  3788.  
  3789.  Figure 2) WinPopupMenu() function 
  3790.  
  3791.  hwndParent and hwndOwner are the parent and owner windows of the menu. 
  3792.  hwndMenu is the handle of the menu to be displayed (see below).  ulX and ulY 
  3793.  are the desktop coordinates at which the menu is to be displayed.  ulItem is 
  3794.  the initial item to be under the mouse and is ignored unless PU_POSITIONONITEM 
  3795.  or PU_SELECTITEM is specified in ulFlags.  ulFlags is a combination of flags 
  3796.  the controls how the function behaves. 
  3797.  
  3798.  Flag                          Description 
  3799.  PU_POSITIONONITEM             Specifies the initial item under the mouse 
  3800.  PU_HCONSTRAIN                 Insures that the menu is within the left and 
  3801.                                right boundaries of the display 
  3802.  PU_VCONSTRAIN                 Insures that the menu is within the top and 
  3803.                                bottom boundaries of the display 
  3804.  PU_NONE                       Specifies that the keyboard was used to invoke 
  3805.                                the menu 
  3806.  PU_MOUSEBUTTON1DOWN           Specifies that mouse button 1 was used to invoke 
  3807.                                the menu 
  3808.  PU_MOUSEBUTTON2DOWN           Specifies that mouse button 2 was used to invoke 
  3809.                                the menu 
  3810.  PU_MOUSEBUTTON3DOWN           Specifies that mouse button 3 was used to invoke 
  3811.                                the menu 
  3812.  PU_SELECTITEM                 Specifies that ulItem is to be selected 
  3813.  PU_MOUSEBUTTON1               Specifies that mouse button 1 can be used to 
  3814.                                select a menuitem 
  3815.  PU_MOUSEBUTTON2               Specifies that mouse button 2 can be used to 
  3816.                                select a menuitem 
  3817.  PU_MOUSEBUTTON3               Specifies that mouse button 3 can be used to 
  3818.                                select a menuitem 
  3819.  PU_KEYBOARD                   Specifies that the keyboard can be used to 
  3820.                                select a menuitem 
  3821.  
  3822.  Since WM_CONTEXTMENU gives you window coordinates and WinPopupMenu() expects 
  3823.  desktop coordinates, you will either have to call WinMapWindowPoints() to 
  3824.  convert from one to the other or call WinQueryPointerPos() to simply retrieve 
  3825.  the desktop coordinates of the mouse. 
  3826.  
  3827.  From where do you get the value for hwndMenu?  You have two options: you can 
  3828.  load it just prior to calling WinPopupMenu() or you can load it during the 
  3829.  WM_CREATE processing and save the value in a structure pointed to by your 
  3830.  window words.  Using the latter is acceptable; however, popup menus are 
  3831.  usually a frequently used resource, so performance might suffer slightly if 
  3832.  you load and destroy the menu everytime it is requested.  This is especially 
  3833.  evident if you are running the application from a network- mapped drive.  If 
  3834.  you still decide to do this, you can destroy the menu using the 
  3835.  WinDestroyWindow() function when you receive the WM_MENUEND message. 
  3836.  
  3837.  WM_MENUEND 
  3838.  
  3839.  This message is sent when a menu or one of its pull-downs has finished the 
  3840.  selection process. 
  3841.  
  3842.      SHORT1FROMMP(mpParm1) - specifies the identifier of the menu who is 
  3843.       finished the selection process. 
  3844.      HWNDFROMMP(mpParm2) - specifies the handle of the menu. 
  3845.  
  3846.  Regardless of when you decide to load the menu, you will have to use 
  3847.  WinLoadMenu() to load the menu template. 
  3848.  
  3849.   WinLoadMenu(hwndFrame,hmodDll,ulResourceId);
  3850.  
  3851.  Figure 3) WinLoadMenu() function 
  3852.  
  3853.  hwndFrame is the handle of the frame to which the menu is to be attached. In 
  3854.  the `old' days, when menus were simply action bars, you would indeed specify 
  3855.  the frame window handle here, and the function would automatically assign the 
  3856.  window identifier FID_MENU to the loaded menu, attach it to the frame, and 
  3857.  `reflow' the frame window.  Since we have a popup menu - which we don't want 
  3858.  to be displayed - we will use HWND_OBJECT here.  hmodDll is the module handle 
  3859.  containing the menu template.  ulResourceId is the menu template identifier. 
  3860.  Menu Messages 
  3861.  
  3862.  We now need to look at more of the messages that we need to interact with the 
  3863.  control.  The MM_QUERYITEM and MM_SETITEM messages are used to query 
  3864.  information about and set information for a node in the menu tree, whether it 
  3865.  is a branch or leaf node.  Both messages have the same parameters: 
  3866.  
  3867.      SHORT1FROMMP(mpParm1) specifies the identifier of the node to search for 
  3868.      SHORT2FROMMP(mpParm1) specifies whether or not submenus should be 
  3869.       searched also 
  3870.      PVOIDFROMMP(mpParm2) points to a MENUITEM structure. 
  3871.  
  3872.   typedef struct {
  3873.        SHORT iPosition;
  3874.        USHORT afStyle;
  3875.        USHORT afAttribute;
  3876.        USHORT id;
  3877.        HWND hwndSubMenu;
  3878.        ULONG hItem;
  3879.   } MENUITEM,*PMENUITEM;
  3880.  
  3881.  Figure 4) MENUITEM structure 
  3882.  
  3883.  iPosition is the 0-based position of the item within its parent.  afStyle and 
  3884.  afAttribute are the MIS_ and MIA_ flags associated with the item.  id is the 
  3885.  numeric identifier of the item.  hwndSubMenu is the handle of the submenu 
  3886.  associated with this item if the MIS_SUBMENU flag is specified in the afStyle 
  3887.  field.  hItem is a 4-byte application-usable area that is associated with the 
  3888.  item. 
  3889.  
  3890.  As I stated in issue 3-6, a few people had asked about the buttons that are to 
  3891.  the right of certain menuitems.  The submenus associated with these are said 
  3892.  to be a conditionally cascading submenu - the word `conditionally' comes from 
  3893.  the behavior of the submenu, which is conditional on how the user interacts 
  3894.  with it.  If the user simply clicks on the text that contains the submenu, the 
  3895.  default item is sent to the application via the WM_COMMAND message. 
  3896.  
  3897.  Although an MIS_CONDITIONALCASCADE style exists, the resource compiler (when I 
  3898.  last checked) did not recognize this as a valid flag.  So, this is added to 
  3899.  the list of things that needs to be done to implement this user interface 
  3900.  feature. 
  3901.  
  3902.      Set the style of the submenu to include MIS_CONDITIONALCASCADE 
  3903.      Set the default menuitem 
  3904.      Check the default menuitem for user-feedback 
  3905.  
  3906.  The first item can only be done using the MM_QUERYITEM and MM_SETITEM messags. 
  3907.  Since this is a fairly frequently needed function, I created the 
  3908.  setCascadeDefault() function, which is included in cascade.zip. 
  3909.  
  3910.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3911.  
  3912.  
  3913. ΓòÉΓòÉΓòÉ 12.2. From CUA 89 to CUA 91 Style Menus ΓòÉΓòÉΓòÉ
  3914.  
  3915. From CUA 89 to CUA 91 Style Menus 
  3916.  
  3917. I have included with this month's column the MENU sample, which has been 
  3918. `ported' to use popup menus instead of the old-style menus.  In doing so, I 
  3919. kept track of the changes that were necessary to give you an idea of the things 
  3920. that need to be done to convert your application to the `new look.' 
  3921.  
  3922.      Remove FCF_MENU from the frame creation flags passed to 
  3923.       WinCreateStdWindow(). 
  3924.      Add hwndMenu to instance data structure. 
  3925.      Load the menu in WM_CREATE and store the handle in the instance data. 
  3926.      Add processing for WM_CONTEXTMENU (#define INCL_WININPUT for the message 
  3927.       and #define INCL_WINPOINTERS for pointer stuff). 
  3928.      Change references of WinWindowFromID(pidData->hwndFrame,FID_MENU) to 
  3929.       pidData->hwndMenu. 
  3930.  
  3931.  This list is by-no-means conclusive, but it shows you what I had to do so that 
  3932.  you have a rough idea of what you will also need to do. 
  3933.  
  3934.  EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3935.  
  3936.  
  3937. ΓòÉΓòÉΓòÉ 12.3. Conclusion ΓòÉΓòÉΓòÉ
  3938.  
  3939. Conclusion 
  3940.  
  3941. This concludes our look at the menu control.  As always, questions and comments 
  3942. are welcome via my email address.  Next month, we'll continue our journey, but 
  3943. I have no idea where it will take us at this time.  Keep reading! 
  3944.  
  3945. EDM/2 - Sept 1995 - Volume 3, Issue 8 
  3946.  
  3947.  
  3948. ΓòÉΓòÉΓòÉ 13. Contributors to this Issue ΓòÉΓòÉΓòÉ
  3949.  
  3950. Contributors to this Issue 
  3951.  
  3952. Are You a Potential Author? 
  3953.  
  3954. We are always looking for authors.  If you have a topic about which you would 
  3955. like to write, send a brief description of the topic electronically to any of 
  3956. the editors, whose addresses are listed below, by the 15th of the month before 
  3957. the month in which your article will appear.  This alerts us that you will be 
  3958. sending an article so that we can plan the issue layout accordingly. After you 
  3959. have done this, get the latest copy of the Article Submission Guidelines from 
  3960. hobbes.nmsu.edu in the /os2/newsltr directory.  (The file is edmsub.zip.)  The 
  3961. completed text of your article should be sent to us no later than five days 
  3962. prior to the last day of the month; any articles received after that time may 
  3963. be pushed to the next issue. 
  3964.  
  3965. The editors can be reached at the following email addresses: 
  3966.  
  3967.      Larry Salomon - os2man@panix.com (Internet). 
  3968.      Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet). 
  3969.  
  3970.  ____________________________________________________________ 
  3971.  
  3972.  Edward Boykin 
  3973.  
  3974.  Ed Boykin will be graduated this winter from Georgia Institute of Technology 
  3975.  with a Bachelor Degree in Aerospace Engineering.  He has been studying 
  3976.  programming on his own for about three years and will probably be continuing 
  3977.  at Tech to get a Master's degree in Computer Science or Engineering.  His 
  3978.  current OS/2 projects include a POP and SMTP e-mail program for OS/2 and other 
  3979.  network client/server projects.  He is currently working as an intern for 
  3980.  Racetrac Petroleum Corp, doing client/server programming using Microsoft 
  3981.  Windows NT and Oracle. 
  3982.  
  3983.  He can be reached at gt5584e@acme.gatech.edu. 
  3984.  
  3985.  ____________________________________________________________ 
  3986.  
  3987.  Dave Briccetti 
  3988.  
  3989.  For those of you who don't know me, I'll tell you a little about myself.  I 
  3990.  have been developing applications for OS/2 since 1987, as an independent 
  3991.  developer and consultant.  I am a cofounder and the president of the OS/2 Bay 
  3992.  Area User Group, a large, independent organization of OS/2 users and 
  3993.  developers.  Most of the development work I have done has been with C and C++ 
  3994.  and PM, in the areas of business and scientific programming. 
  3995.  
  3996.  Recently I have felt compelled to do something flashy and fun; either games or 
  3997.  edutainment software development for OS/2.  I bought several great books on 
  3998.  graphics and game programming, and now IBM has released Beta 1 of its OS/2 
  3999.  Warp Entertainment Toolkit.  I'm ready! 
  4000.  
  4001.  ____________________________________________________________ 
  4002.  
  4003.  Peter Childs 
  4004.  
  4005.  Peter is an undergraduate Computer Science student at the Flinders University 
  4006.  in South Australia.  Last year he studied Mechanical Engineering at the 
  4007.  Adelaide University, and the year before he was a Missile Number serving with 
  4008.  111 Air Defense Bty (Lt) of the Australian Army. 
  4009.  
  4010.  Peter is a member of the South Australian Os/2 User Group and the author of 
  4011.  the POPWatch mailbox watching program (OS/2), and the Inf-HTML suite, which 
  4012.  allows batch or runtime conversion of OS/2 INF files to HTML (platform 
  4013.  independent). 
  4014.  
  4015.  You may reach Peter 
  4016.  
  4017.  ...via email: 
  4018.  
  4019.  pjchilds@apanix.apana.org.au - Internet 
  4020.  
  4021.  ...World Wide Web homepage 
  4022.  
  4023.  http://www.apanix.apana.org.au/~pjchilds/ - WWW 
  4024.  
  4025.  ...via phone 
  4026.  
  4027.  61-8-2787381 
  4028.  
  4029.  ____________________________________________________________ 
  4030.  
  4031.  Michael T. Duffy 
  4032.  
  4033.  Michael is a recent graduate of the University of Southern California and has 
  4034.  degrees in Cinema Production and East Asian Languages and Cultures.  His 
  4035.  computer skills are self- taught, and he has been programming for OS/2 since 
  4036.  about December of 1994.  Michael is working on breaking into the game 
  4037.  development industry, and has been working towards that goal for a number of 
  4038.  months.  He expects to release his first game, an OS/2 shooter, later this 
  4039.  year. 
  4040.  
  4041.  Michael can be reached on the internet at mduffy@ionet.net. 
  4042.  
  4043.  ____________________________________________________________ 
  4044.  
  4045.  Larry Salomon Jr. 
  4046.  
  4047.  Larry Salomon Jr.  has been developing OS/2 applications since version 1.1 in 
  4048.  1989.  He has written numerous applications, including the Scramble applet 
  4049.  that was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and 
  4050.  Screen Capture trio that has been distributed on numerous CD-ROMs. 
  4051.  
  4052.  Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C 
  4053.  Programming (Wiley-QED).  Finally, he is the CEO/President of IQPac Inc. which 
  4054.  is responsible for the publication of EDM/2 and he is a frequent contributor 
  4055.  to the publication. 
  4056.  
  4057.  Larry can be reached electronically via the Internet at os2man@panix.com. 
  4058.  
  4059.  ____________________________________________________________ 
  4060.  
  4061.  Eric Slaats 
  4062.  
  4063.  Eric Slaats teaches information technology at the Hogeschool Eindhoven, 
  4064.  Faculty of Economics Sr.  Business Informatics.  Besides teaching, he has 
  4065.  written a number of books.  Currently, he is researching the behavior of 
  4066.  neural networks in a financial environment.  He started programming OS/2 PM to 
  4067.  build an interface for a Neural network problem in september 1994. 
  4068.  
  4069.  Eric can be reached electronically via the internet at e.slaats@fe.hse.nl. 
  4070.  
  4071.  ____________________________________________________________ 
  4072.  
  4073.  Carsten Whimster 
  4074.  
  4075.  Carsten is an undergraduate Computer Science student at the University of 
  4076.  Waterloo.  He is currently in fourth year, and enjoying it immensely.  He uses 
  4077.  Watcom C/C++ 10.0a and Watcom VX-REXX 2.0b.  Carsten is the author of some 
  4078.  commandline utilities, and POV-Panel/2.  He is currently trying to learn 
  4079.  enough GPI programming to do a remake of the old video game Qix.  He is also a 
  4080.  TEAM-OS/2 member, and has adopted a little computer store called The Data 
  4081.  Store in Waterloo, Ontario, which promptly hired him part-time. 
  4082.  
  4083.  You may reach Carsten... 
  4084.  
  4085.  ...via email: 
  4086.  
  4087.  bcrwhims@undergrad.math.uwaterloo.ca - Internet 
  4088.  
  4089.  ...World Wide Web homepage (incomplete; aren't they all): 
  4090.  
  4091.  http://www.undergrad.math.uwaterloo.ca/~bcrwhims - WWW 
  4092.  
  4093.  ...via snail mail:  Carsten Whimster 318A Spruce Street Waterloo, Ontario 
  4094.  Canada N2L 3M7 
  4095.  
  4096.  ...via phone 
  4097.  
  4098.  (519) 886-2439 
  4099.  
  4100.  ____________________________________________________________ 
  4101.  
  4102.  Gordon Zeglinski 
  4103.  
  4104.  Gordon Zeglinski is a freelance programmer/consultant who received his 
  4105.  Master's degree in Mechanical Engineering with a thesis on C++ sparse matrix 
  4106.  objects.  He has been programming in C++ for 6 years and also has a strong 
  4107.  background in FORTRAN.  He started developing OS/2 applications with version 
  4108.  2.0 . 
  4109.  
  4110.  His current projects include a client/server communications program that 
  4111.  utilitizes OS/2's features which has entered beta testing.  Additionally, he 
  4112.  is involved in the development of a "real-time" automated vehicle based on 
  4113.  OS/2 and using C++ in which he does device driver development and designs the 
  4114.  applications that comprise the control logic and user interface. 
  4115.  
  4116.  He can be reached via the Internet at zeglins@cc.umanitoba.ca. 
  4117.  
  4118.  ____________________________________________________________ 
  4119.  
  4120.  Network Distributors 
  4121.  
  4122.  These people are part of our distribution system to provide EDM/2 on networks 
  4123.  other than the Internet.  Their help to provide access to this magazine for 
  4124.  others is voluntary and we appreciate them a lot!  ┬╖   Paul Hethmon 
  4125.  (phethmon@utk.edu) - Compuserve ┬╖   Gess Shankar (gess@knex.mind.org) - 
  4126.  Internet ┬╖   Jason B. Tiller (PeerGynt@aol.com) - America On-line ┬╖   David 
  4127.  Singer (singer@almaden.ibm.com) - IBM Internal ┬╖   Jesper Nielsen 
  4128.  (afdata@pop02.ny.us.ibm.net) - Denmark BBS's 
  4129.  
  4130.  If you would like to become a "network distributor", be sure to contact the 
  4131.  editors so that we can give you the credit you deserve! 
  4132.  
  4133.  EDM/2 - Sept 1995 - Volume 3, Issue 8