home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 32 Periodic / 32-Periodic.zip / edmi3-7.zip / EDMI3-7.INF (.txt) < prev    next >
OS/2 Help File  |  1995-08-03  |  456KB  |  4,249 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Aug 1995 Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.                   The Electronic Developer's Magazine for OS/2
  5.                       Portions copyright (c) by IQPac Inc.
  6.                                 Volume 3, issue 7
  7.  
  8. Administrivia 
  9.  
  10. There has to be a section of Murphy's law's that deal with computers and 
  11. specifically with making announcements.  Immediately after announcing the EDM/2 
  12. Web site, the address changed and EDM/2 missed the next issue.  The new URL is 
  13. http://os2man.netsysdev.telerate.com . Ah, what three letters can do to a 
  14. person. 
  15.  
  16. The Web site is growing nicely.  A Gotcha section has been added which will 
  17. grow into a repository of programming pitfalls, and it utilizes HTML forms to 
  18. allow you to contribute directly to the page.  Additionally, a weekly From the 
  19. editor section was added to allow me to tell you about things that you should 
  20. know as an OS/2 developer in a more timely fashion.  Let's face it; if you read 
  21. things once a month here, there's a good chance that the information is no 
  22. longer valid by that time.  Finally, a Feedback section was added to give you 
  23. the opportunity to sound off; tell us what you think about anything.  We'll be 
  24. glad for your feedback. 
  25.  
  26. In any case, as we get more time, more things will get updated so keep a 
  27. lookout and send us any feedback you have! 
  28.  
  29. Errata 
  30.  
  31. Last issue's article on IPC Between DOS Processes was incorrectly described as 
  32. having been authored by Mike Ruddy.  It was instead written by Leif N. Eriksen. 
  33.  
  34. Infoworld, Brian Livingston, et al. 
  35.  
  36. Those of you who are fortunate enough to read Infoworld on a regular basis 
  37. probably know who Brian Livingston is - he is a "pro-Windows and everything 
  38. else can go to hell" kind of a person - but in his July 24 column, he said 
  39. something quite upsetting.  Paraphrased, "if you are one of the 3 people who 
  40. don't have a preview copy of Windows 95..."  I've seen this attitude before and 
  41. always make sure I send off some email to correct the situation; this time was 
  42. no different.  I told Brian that I've been using OS/2 since 1989 and have been 
  43. quite happy with it.  I have had no reason nor desire to go to Windows and 
  44. probably never will.  I selected the "Send" button and figured that was that. 
  45.  
  46. Boy was I wrong. 
  47.  
  48. His response was infuriating.  Not only did he insult me by telling me that I 
  49. should be saving his columns for the general availability of Windows 95, but he 
  50. added "salt to the wound" by telling me in a post script that "the other two 
  51. people also complained." 
  52.  
  53. In the words of Bugs Bunny, "this means war." 
  54.  
  55. My reply to him can be found in the From the editor section for the week 
  56. beginning July 24.  The only thing I request is, if you are like me and are 
  57. happy with OS/2, that you drop him a line to tell him so.  His email address is 
  58. brian_livingston@infoworld.com  . I am not encouraging you to flame him to a 
  59. cinder.  Simply let him know which operating system you will use on August 24. 
  60. The amount of mail coming into his mailbox should help him to adjust his 
  61. opinion. 
  62.  
  63. Stewart Alsop, on the other hand, always seems to come on strong in his 
  64. columns.  While I won't deny that he has a bite, he did surprise me also this 
  65. past week.  I have had email "discussions" (more like me venting a bit of 
  66. frustration at him) with him and have always considered him to be another 
  67. Windows bigot.  I told him this in a recent email to which he responded, again 
  68. paraphrasing, "that is an amusing concept."  He enforced that with the claim 
  69. that he has used a Mac since 1985, a fact I did not remember until after I read 
  70. that.  Well, at least I can't claim that he's so anti-IBM because he's so 
  71. pro-Windows.  Maybe there is a bit of objectivity in him after all... 
  72.  
  73. And Nicholas Petreley has to be out on a limb there.  He's the only vocal 
  74. pro-OS/2 writer there (the keyword is "vocal") and that has to be stressful. 
  75. Help him out, people; if you know of some hot new product or development tool, 
  76. let him know about it.  He'll thank you for it, guaranteed.  His address is 
  77. nicholas_petreley@infoworld.com . 
  78.  
  79. It's That Time Again 
  80.  
  81. Gordon will, starting this issue, begin another round of C++ compiler 
  82. comparisons, and he definitely has some interesting things to tell you. He 
  83. plans to review two compilers per month, but that will depend on his schedule 
  84. in future months.  A related note is that, because this issue is quite large 
  85. due to the screen shots included in the compiler review, the Introduction to PM 
  86. Programming column will not be a part of this month's issue. 
  87.  
  88. ...And Speaking of Reviewing 
  89.  
  90. I have received a couple of tentative offers from people willing to try to be 
  91. our Software Review columnist.  If you are interested, simply let me know; the 
  92. only commitment you have to keep is to review one development-related 
  93. application per month. 
  94.  
  95. Spread the Word 
  96.  
  97. If you haven't visited the #os/2 channel on IRC yet, it's about time you did. 
  98. There are IRC clients for most platforms and it isn't really that addicting 
  99. <grin>.  In #os/2, you can get your questions answered about configuration 
  100. problems, user problems, and even programming problems.  It's helpful for the 
  101. "I need the answer now" problem. Some problems go unanswered but it's always 
  102. worth a try, and the "regulars" are great fun.  I'm always in there (with the 
  103. nickname of Q--, unsurprisingly) and so are many other very knowledgeable 
  104. people. 
  105.  
  106. Please Wait Another Month 
  107.  
  108. I made a promise in June to demonstrate how to make transparent windows, but 
  109. this month has kept me quite busy, and I will continue to be so until August 
  110. 15, when the ColoradOS/2 presentations are due to Wayne Kovsky.  In fact, if I 
  111. hadn't cancelled last month's issue, I would have done so this month.  Please 
  112. be patient; I will fulfill this promise next issue. 
  113.  
  114. One Final Note 
  115.  
  116. This is wrong, but I'm going to say it anyway:  the 2nd edition of my book 
  117. should hit the shelves in the U.S. on approximately September 1, according to 
  118. John Wiley and Sons.  It is entitled, The Art of OS/2 Warp Programming.  If you 
  119. want more information, stop by the "official" web site, also located at 
  120. http://os2man.netsysdev.telerate.com. 
  121.  
  122. Enjoy this issue! 
  123.  
  124.  
  125. ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
  126.  
  127. Copyright Notice 
  128.  
  129. EDM/2 is published by IQPac Inc.  IQPac Inc. can be reached via U.S. Mail at 
  130. the following address: 
  131.  
  132. IQPac Inc.
  133. 7 East Broadway, Box 804
  134. New York, NY 10038
  135. U.S.A.
  136.  
  137.  Editor-in-chief     Larry Salomon Jr. 
  138.  Associate editor    Carsten Whimster 
  139.  Contributing editor Gordon Zeglinski 
  140.  
  141.  CEO/President       Larry Salomon Jr. 
  142.  
  143.  All material is copyrighted by its original author.  No part of this magazine 
  144.  may be reproduced without permission from the original author. 
  145.  
  146.  This publication may be freely distributed in electronic form provided that 
  147.  all parts are present in their original unmodified form.  A reasonable fee may 
  148.  be charged for the physical act of distribution; no fee may be charged for the 
  149.  publication itself. 
  150.  
  151.  Neither IQPac Inc. nor this publication are affiliated with International 
  152.  Business Machines Corporation. 
  153.  
  154.  OS/2 is a registered trademark of International Business Machines Corporation. 
  155.  Other trademarks are property of their respective owners.  Any mention of a 
  156.  product in this publication does not constitute an endorsement or affiliation 
  157.  unless specifically stated in the text. 
  158.  
  159.  The OS/2 Accredited Logo is a trademark of International Business Machines 
  160.  Corporation and is used by IQPac Inc. under license.  This On-line Publication 
  161.  is independently produced by IQPac Inc. and IBM is not responsible in any way 
  162.  for its contents. 
  163.  
  164.  IQPac Inc. is an accredited member of the IBM Independent Vendor League. 
  165.  
  166.  Copyright Notice - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  167.  
  168.  
  169. ΓòÉΓòÉΓòÉ 3. Letters ΓòÉΓòÉΓòÉ
  170.  
  171. Letters 
  172.  
  173. To write to EDM/2, send your email to os2man@panix.com and use the Subject: 
  174. line "Letters". 
  175.  
  176. 'Games' Was A Hit 
  177.  
  178. Lachlan O'Dea (drizzt@cc.monash.edu.au) writes: 
  179.  
  180. Thank you for your excelent Gearing Up For Games article in EDM/2.  It was very 
  181. interesting and easy to understand.  I'm a good programmer, but I'm relatively 
  182. new to OS/2 and I've never touched DIVE. 
  183.  
  184. I look forward to future articles by you on game programming in OS/2. EDM/2 
  185. keeps getting better and better! 
  186.  
  187. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  188.  
  189. ...So Was 'EXE Optimization' 
  190.  
  191. Steve Snyder (ssnyder@icon-stl.net) writes: 
  192.  
  193. Having just read your very good articles on EXE optimization ("Building Smaller 
  194. OS/2 Executables", EDM issues 3-3 and 3-4), I have a question. 
  195.  
  196. It concerns the use of the LINK386 /BASE switch.  You state that the use of 
  197. /BASE:0x10000 eliminates the need for fixups, making the EXE smaller and the 
  198. loading of it faster.  I tried it on my program and in fact the 1.5MB EXE size 
  199. shrunk by 80k! 
  200.  
  201. Now my question:  Is there a downside to using this switch?  If not, I don't 
  202. understand why IBM did not make this the default.  This looks so much like a 
  203. free lunch that I'm looking for the hidden cost. 
  204.  
  205. Thanks for the informative articles. 
  206.  
  207. Pete Cassetta responds: 
  208.  
  209. Thanks for your nice comments about my articles. 
  210.  
  211. I was very glad to hear that your 1.5 MB EXE shrunk by 80K when you began using 
  212. the /BASE:0x10000 linker switch!  I suppose this switch does sound like 
  213. something for nothing, but in this case you can have a free lunch.  There is 
  214. absolutely no downside to using this switch.  If you benchmark your program 
  215. carefully, you should see an improvement in load time as well.  This switch 
  216. simply causes the linker to resolve internal fixups at link time instead of 
  217. leaving them in there to be resolved at load time.  OS/2 allows this because 
  218. its designers wisely decided that all EXEs would load at a base address of 
  219. 0x10000.  Hence the load address is always known at link time. 
  220.  
  221. The question of why LINK386 doesn't use /BASE:0x10000 by default for EXEs is a 
  222. good one.  I really don't know the answer, though I imagine there must be some 
  223. historical or philisophical reason.  You may be interested to know that the 
  224. authors of C-Set++ agree with you that this switch should be on by default.  If 
  225. you compile and link by calling the ICC program that comes with C-Set++, it 
  226. turns on the /BASE:0x10000 switch by default when calling LINK386. ICC actually 
  227. turns on three size-related switches by default: 
  228.  
  229. /align:16 /exepack /base:65536 (taken from an ICC-generated command-line) 
  230.  
  231. Because of this, many programs built with C-Set++ get these switches turned on 
  232. with no explicit effort on the part of their author.  If you are using C-Set++, 
  233. then I expect you wrote your own makefile which calls LINK386 directly.  In 
  234. this case you have to turn on the /BASE switch yourself. 
  235.  
  236. So don't fear the /BASE:0x10000 switch; it is a friend and should be used when 
  237. linking all your EXE files. 
  238.  
  239. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  240.  
  241. A Request or Two 
  242.  
  243. Paul D. Walker (pdwalker@hk.super.net) writes: 
  244.  
  245. I have looked forward to the 'zine since I first discovered and read all the 
  246. issues last year.  I have enjoyed the publication as, I am sure, many others 
  247. have.  Since you did not receive any letters last month, I thought that I would 
  248. at least break the silence and give you my support (whoopee!)  Well, enough of 
  249. that. 
  250.  
  251. What I would like to see is either a continuation of installable file systems 
  252. (and the nuts and bolts of how to), or something on the internals (as far as 
  253. anyone can find out) of HPFS. 
  254.  
  255. In general, I have found the third year of your publication (so far) to be the 
  256. best yet.  I especially enjoyed the articles on reducing code size, especially 
  257. with todays programs getting bloated beyond everything imaginable (my simple 
  258. clipper programs frequently go over 700KB nowadays because of the overhead of 
  259. my library on top of clippers library.) 
  260.  
  261. Please keep up the good work.  Please continue your introduction to PM 
  262. programming (as one day soon I will go back and read all the articles and start 
  263. programming under OS/2 myself...or wait for Visual Age (*grin*) and any other 
  264. topic that you might be interested in yourself.  If you are interested in a 
  265. particular thing, then you can bet that someone else will be.  (At least that 
  266. is what an older more experienced DJ told me years ago when I was learning the 
  267. trade...) 
  268.  
  269. Looking forward to the next issue... 
  270.  
  271. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  272.  
  273. Dirk Wissmann (wissmann@genesis.westend.com) writes: 
  274.  
  275. I absolutely appreciate your EDM/2 and I like the articles written there. 
  276. Especially the "Introduction to PM Programming" is a favourite one, which I 
  277. always read to increase my knowledge. 
  278.  
  279. But now I have reached the point where I have to use something, that was 
  280. covered in no issue until now (including Vol. 3 Iss. 6):  creation and handling 
  281. of notebooks. 
  282.  
  283. When looking on the themes which were published in the section PM Programming, 
  284. almost everything was important.  And in my opinion, creating a notebook is as 
  285. important as all the other themes - just think about making your PM application 
  286. configurable. 
  287.  
  288. So how about this theme?  Will this be something for an EDM/2 in the near 
  289. future, or will it take a longer time until it will show up? 
  290.  
  291. Larry Salomon responds: 
  292.  
  293. As you might imagine, EDM/2 is dependent on the voluntary works of the 
  294. contributors, so we cannot give a satisfactory answer since we do not know who 
  295. will be submitting what.  While I would love to get to the "meat" of things in 
  296. the column, I want to avoid rushing the column since I felt that was a 
  297. significant problem with the first effort at it.  PM programming is quite 
  298. difficult; rushing things would leave out significant details in all likelihood 
  299. and might confuse the readers. 
  300.  
  301. Your feedback has been noted, however, and I will try to fish for someone to 
  302. write an article on this topic. 
  303.  
  304. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  305.  
  306. Solving a Programming Problem 
  307.  
  308. Mark Mathews (mmathews@genesis.nred.ma.us) writes: 
  309.  
  310. I'm slowly porting DEU 5.3 (DOOM editor.  DOOM?  What's DOOM?  <grin>) over to 
  311. OS/2.  It's now drawing maps.  I'm trying to figure out how to use mouse 
  312. messages.  I tried using WM_BUTTON1CLICK and WM_BUTTON2CLICK but if I try to 
  313. double click the mouse I still activate the WM_BUTTON1CLICK.  What I want to do 
  314. is to click once to mark an object on the map or to click twice and edit the 
  315. object.  I don't have to mark an object to edit it.  'Mark' is used to select 
  316. more than 1 item.  So how do I distinguish between all these different mouse 
  317. messages? 
  318.  
  319. Larry Salomon responds: 
  320.  
  321. There is no way to automatically do it, so you have to use some voodoo magic to 
  322. get what you want.  When you get the WM_BUTTON1CLICK message, call 
  323. WinQuerySysValue(HWND_DESKTOP,SV_DBLCLKTIME) and start a timer (WinStartTimer) 
  324. with the value returned.  If you get a WM_BUTTON1DBLCLK message before you get 
  325. the appropriate WM_TIMER message, then you process the "double click event" 
  326. otherwise you process the "single click event". 
  327.  
  328. Don't forget to call WinStopTimer! 
  329.  
  330. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  331.  
  332. cdray@icis.on.ca writes: 
  333.  
  334. I've used just about every PM control (including containers) with great 
  335. success, but it may be the lowly Button control which finally drives me insane. 
  336.  
  337. My particular problem is with the BS_BITMAP style.  I have used the BS_ICON 
  338. style with no problem.  I am attempting to create a button, with bitmap, in the 
  339. client area of my main window using WinCreateWindow.  When I specify BS_ICON 
  340. and the appropriate .ICO file, the button is displayed and functions correctly. 
  341. When I specify BS_BITMAP and a .BMP file, nothing is displayed. 
  342.  
  343. Any help would be greatly appreciated! 
  344.  
  345. Larry Salomon responds: 
  346.  
  347. This was a bug in the 2.x toolkit.  Are you using that or the Warp toolkit? I 
  348. haven't verified the "fix" that I have hoped for in the latter. 
  349.  
  350. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  351.  
  352. Web Site Feedback 
  353.  
  354. Kevin Porter (kporter@nmia.com) writes: 
  355.  
  356. This may be beyond your control but an "expand all" button when reading the 
  357. magazine would be very helpful, since there's a significant delay each time an 
  358. expand is done. 
  359.  
  360. It's nice to find the stuff on-line, i've been off the distribution since my 
  361. account moved a while ago and it's nice to see your work continuing/maturing. 
  362. Hope it's going well for you.  Keep up the good work! 
  363.  
  364. EDM/2 responds: 
  365.  
  366. Thanks for the compliments and comments.  We are held hostage by Peter Childs, 
  367. the author of the INF-HTML package until we get time to convert the issues to 
  368. HTML format directly. 
  369.  
  370. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  371.  
  372. Mark Noble (mnoble@ukanvm.cc.ukans.edu) writes: 
  373.  
  374. The EDM/2 WWW setup is well done, however there's one thing that I'd like to 
  375. see.  I don't know what's involved in this, but if it isn't to difficult, is 
  376. there any way you could "gather" all of the Q&A sections into one page? If the 
  377. load on the server gets a little high, this might help. 
  378.  
  379. [Editor's note - Mark did this for us, but we have been too busy to incorporate 
  380. it into the Web site.] 
  381.  
  382. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  383.  
  384. Documentation Error 
  385.  
  386. jrb@mfltd.co.uk writes: 
  387.  
  388. I received the info doc telling me how to subscribe to EDM/2 and where to find 
  389. the back issues via FTP.  I think the location is wrong and needs updating: 
  390.  
  391. It said hobbes.nmsu.edu /pub/os2/32bit/program/newsltr, but I found it in 
  392. /os2/newsltr instead. 
  393.  
  394. EDM/2 responds: 
  395.  
  396. Was this doc obtained from the mail server (edm2-info@knex.mind.org) or from 
  397. some other location?  If the former, it should have been changed by now, so you 
  398. might re- request it to check.  If from some other location, I have no control 
  399. over this, but you could send email to the site admin and tell them to get the 
  400. document again. 
  401.  
  402. Thanks for pointing this out. 
  403.  
  404. Letters - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  405.  
  406.  
  407. ΓòÉΓòÉΓòÉ 4. Announcements ΓòÉΓòÉΓòÉ
  408.  
  409. Announcements 
  410.  
  411. Learn REXX with The REXX Cookbook and The Rexx Files 
  412.  
  413. Author: Merrill Callaway 
  414.  
  415. Publisher: 
  416.  
  417. Whitestone
  418. 511-A Girard Blvd SE
  419. Albuquerque, NM 87106  USA
  420. (505) 268-0678
  421. email 5979987@mcimail.com
  422.  
  423. Product Description and Ordering Information 
  424.  
  425. The REXX Cookbook is a unique tutorial designed to teach anyone, even 
  426. non-programmers, to program in REXX by presenting detailed explanations of over 
  427. 40 useful REXX programs.  These programs and several more are on the companion 
  428. disk THE REXX FILES.  Those who have experienced the frustration of trying to 
  429. write real world code after finding only fragmentary examples in reference 
  430. books will really appreciate the programs in this book. 
  431.  
  432. Charles Daney of Quercus Systems and author of Programming in REXX, published 
  433. by McGraw Hill, had this to say to Mr.  Callaway after he reviewed it: 
  434.  
  435. "I was really impressed with the amount of work you put in on this.  It's one 
  436. of the most detailed computer books I've ever seen, and not just trivial detail 
  437. either, but good solid information.  And some of your examples are among the 
  438. best I've seen anywhere.  The stuff on PostScript, SQL, DB2/2, AmiPro, etc. 
  439. should be really valuable to many." 
  440.  
  441. Callaway works from the premise that reference books on programming have too 
  442. high a degree of abstraction and generalization to be tutorials, since they 
  443. attempt to cover every case for every instruction.  Learners must decipher 
  444. templates and syntax diagrams rather than view explicit code in the context of 
  445. a complete, concrete program.  His book makes learning REXX far easier than 
  446. ever before, because readers can see actual code used and explained in context. 
  447. It is a bonus that the book's programs are so useful in their own right.  There 
  448. was as much software development as writing to produce this book.  For instance 
  449. one example project is an Inter-Process Control REXX program that combines 
  450. VX-REXX by WATCOM, REXX and DB2/2 by IBM, and AmiPro by Lotus Development. 
  451.  
  452. Another unique program uses REXX and PostScript together to print envelopes 
  453. quickly without needing to open a word processor.  It even keeps a database of 
  454. your personal addresses handy.  There are some essential system utility 
  455. programs to back up your .INI files, some EPM and TSPF editor macros, and even 
  456. a program to teach you how to use the parse instruction.  The level of 
  457. difficulty is graduated so the book is suitable for beginners and experts 
  458. alike.  Everyone will find useful REXX code in The REXX Cookbook.  Combined 
  459. with any standard or online REXX reference, it rounds out a COMPLETE COURSE in 
  460. REXX FLUENCY.  Callaway says, "The REXX Cookbook is the very book I wished I'd 
  461. had when I was learning to program in REXX!" 
  462.  
  463. The REXX Cookbook is OS/2 Accredited. 
  464.  
  465. How to order 
  466.  
  467. VISA/MasterCard orders may email or telephone with credit card number and 
  468. expiration date. 
  469.  
  470. Checks or money orders (made payable to Whitestone) US Bank in US dollars are 
  471. also acceptable (mail to publisher's address above). 
  472.  
  473. Price:  Deluxe Set (book and disk):  $42.90 (book ONLY: $27.95) 
  474.  
  475. Shipping and handling USA:  $5.00
  476. Shipping and handling elsewhere:  $12.00
  477.  
  478. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  479.  
  480. Mindy Ported to OS/2 
  481.  
  482. I have completed a port of Mindy 1.3 to OS/2. 
  483.  
  484. Mindy is an implementation of the Dylan language but Mindy is not Dylan yet. 
  485.  
  486. Dylan is a general-purpose Object Oriented Dynamic Language designed by Apple 
  487. Computer. 
  488.  
  489. Quoting from Apple's Dylan Home Page at 
  490. http://www.cambridge.apple.com/dylan/dylan.html: 
  491.  
  492. "Dylan is a new language developed at Apple.  It is a bold new effort to create 
  493. a powerful, practical tool for writing mainstream commercial applications.  We 
  494. believe it combines the best qualities of static languages (small, fast 
  495. programs) with the best qualities of dynamic languages (rapid development, code 
  496. that's easy to read, write and maintain)." 
  497.  
  498. Credits for Mindy, and therefore 99% of this port, go to the Gwydion Project at 
  499. Carnegie Mellon University. 
  500.  
  501. Mindy is freely available and the modified source and executables have been 
  502. uploaded to hobbes.nmsu.edu.  The file is named mindy13.zip and it should be in 
  503. the /os2/dev32/ directory.  While you are there, get /os2/unix/emx09a/emxrt.zip 
  504. if you don't have it.  It contains DLLs required by the Mindy executables. 
  505. hobbes.nmsu.edu is mirrored at ftp.cdrom.com in /pub/os2/.  I only tested the 
  506. port under OS/2 Warp. 
  507.  
  508. The Gwydion project released Mindy 1.3 but please send bug reports to me if you 
  509. use this port.  They have much better things to do than fix my bugs. <grin> 
  510.  
  511. ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  512.  
  513. Introduction to OS/2 Programming in C Course 
  514.  
  515. From Distributed Systems Laboratories Education Services 
  516.  
  517. The five day course, Introduction to OS/2 Programming in C, is now available. 
  518. DSL can schedule this course at your site, or provide materials under a license 
  519. agreement.  Rates are determined by volume and location (Country).  All courses 
  520. are taught in English, although translation services are available. 
  521.  
  522. The Intro to OS/2 Programming course will begin a complete OS/2 series of 
  523. courses, including Advanced OS/2 Programming, Intro to PM Programming, and 
  524. Advanced PM Programming. 
  525.  
  526. Other courses already available include a two day Intro to OS/2, Overview of 
  527. Object-Oriented Analysis and Design, C/C++ Programming, DCE Architecture and 
  528. Internals, UNIX System Optimization and Performance Evaluation, UNIX System 
  529. calls, Borland's Delphi, and more. 
  530.  
  531. Introduction to OS/2 Programming in C 
  532.  
  533. Course Overview 
  534.  
  535. This five day, instructor-lead course will provide an introduction to 
  536. programming under IBM's OS/2 operating system, v2.x and higher.  The majority 
  537. of the class will be spent in laboratory exercises, interspersed with lecture 
  538. and examples.  This course provides the beginning concepts which are followed 
  539. up in the Advanced OS/2 programming course, and the Presentation Manager 
  540. Programming courses.  As a prerequisite, all students must know and have 
  541. experience with the C programming language.  Familiarity with the Workplace 
  542. Shell, from a user standpoint, is helpful. 
  543.  
  544. Students are welcome to bring a copy of their own source code editor.  The 
  545. standard OS/2 'E' and 'EPM' editors will be provided. 
  546.  
  547. Target Audience 
  548.  
  549. The target audience for this course is Application and System software 
  550. developers, designers, and maintainers. 
  551.  
  552. Course Objectives 
  553.  
  554. This course will provide the student with technical and practical experience 
  555. with: 
  556.  
  557.      Multi-threaded programming 
  558.      The OS/2 Control Program API 
  559.      File and Disk Handling 
  560.      Timing Events 
  561.      Dynamic Memory 
  562.      Semaphores and Queues 
  563.      Dynamic Link Libraries 
  564.  
  565.  For more information, or to schedule a course, contact Gregory Bryant at 
  566.  800-890-8676, 513-698-5108, or fax 513-698- 4490. 
  567.  
  568.  Distributed Systems Laboratories is a division of Delta Music Systems, Inc. 
  569.  
  570.  (OS/2 is a registered trademark of IBM Corporation.) 
  571.  
  572.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  573.  
  574.  SpeedPascal/2 version 1.0 
  575.  
  576.  SpeedPascal/2 is a Borland Pascal 7.0 compatible compiler and an integrated 
  577.  development environment (IDE) with a host of features designed to ease the 
  578.  task of writing OS/2 Presentation Manager(TM) programs.  At last, you can use 
  579.  the productive programmer's language of choice on the world's most productive 
  580.  operating system: 
  581.  
  582.       NO runtime royalites! 
  583.       NO huge support .DLLs! 
  584.       NO lengthy compile times for small programs! 
  585.       NO sluggish interpreted code! 
  586.       NO limits! 
  587.  
  588.  The SpeedPascal/2 environment is a suite of tools centered around a Multiple 
  589.  Document Interface editor.  From the IDE, you can access the power of the 
  590.  SpeedPascal/2 tools: 
  591.  
  592.      A PM-based MDI editor 
  593.      An integrated debugger 
  594.      A 32-bit OS/2 compiler 
  595.      An OS/2 Assembler 
  596.      A Resource Editor and Compiler 
  597.      An Inline Assembler 
  598.      Context sensitive help 
  599.  
  600.  We're pretty proud of our IDE here at SpeedSoft.  If you prefer to use your 
  601.  own editor, that's fine with us.  You still have access to the tools you need: 
  602.  
  603.      A command line compiler 
  604.      A command line assembler 
  605.      A standalone resource editor 
  606.      A command line resource compiler 
  607.  
  608.  SpeedPascal comes complete with electronic versions of: 
  609.  
  610.      The User's Manual 
  611.      The Programmer's Manual 
  612.      The SpeedPascal/2 Language Reference 
  613.      The OPML Reference Manual 
  614.  
  615.  SpeedPascal/2 additionally comes with sample code demonstrating the features 
  616.  of the compiler and OS/2. 
  617.  
  618.  SpeedPascal/2 for OS/2 is just the beginning for SpeedSoft.  We're committed 
  619.  to being a cross-platform solution, and to providing you with the best tools 
  620.  around for any platform.  We're currently at work with major vendors of Pascal 
  621.  products to see that your favorite libraries get ported to SpeedPascal/2. 
  622.  
  623.  More info: 
  624.  
  625.  Download the information brochure at: 
  626.  
  627.  Compuserve:  OS2DF1 forum, REXX/Other, file SPDBRO.TXT 
  628.  
  629.  WWW:  http://xs4all.nl/~atverm/index.html 
  630.  
  631.  Demo Available 
  632.  
  633.  A completely functional demo version is available at the same Compuserve forum 
  634.  and through the Web page.  The demo can also be downloaded by anonymous ftp at 
  635.  130.112.6.2, change to the OS2 directoy and transfer (in binary mode) the file 
  636.  speedos2.zip. 
  637.  
  638.  Limited Time Offer 
  639.  
  640.  From now until July 31st, 1995, SpeedSoft is offering the SpeedPascal/2 
  641.  compiler for the price of $129!  (Sorry, we can't discount the manual 
  642.  hardcopies.)  After this period the price will be $179. 
  643.  
  644.   SpeedSoft USA
  645.   19528 Ventura Blvd. #133
  646.   Tarzana, CA 91356
  647.   (818) 887-3034
  648.  
  649.  For all Benelux customers (Belgium, Netherlands and Luxembourg): 
  650.  
  651.   Horacio Software
  652.   Aardappelmarkt 23
  653.   NL-3311 BA  Dordrecht
  654.   Nederland
  655.   Tel/Fax : +31 ( 78) 147059
  656.   Compuserve : 72072,30
  657.  
  658.  For all other European customers: 
  659.  
  660.   SpeedSoft GbR Nrnberger & Partner
  661.   c/o Rene Nrnberger
  662.   Arthur-Strobel-Str. 12
  663.   09127 Chemnitz
  664.  
  665.   FAX :  +49 (371) 2176173
  666.   Compuserve:  100614,306
  667.   Internet:  speedsoft@special.infox.com
  668.   Support:  support@special.infox.com
  669.   Beta-Tester:  speedpascal.beta@special.infox.com
  670.  
  671.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  672.  
  673.  Technical information about DB2 for OS/2 on WWW 
  674.  
  675.  More than 300 pages of technical information about DB2 for OS/2 (DB2/2) 
  676.  Version 1 available at WWW from http://www.nta.no/brukere/olea/db2book. 
  677.  
  678.  The material is offered as eight PostScript files, and ranges from beginners 
  679.  tutorial to quite complicated.  Areas covered include: 
  680.  
  681.      Tables, views, indexes 
  682.      QM procedures and panels 
  683.      QM command interface 
  684.      All aspects of SQL 
  685.      Programming with REXX, C, C++, and Smalltalk 
  686.      Logging and recovery 
  687.      Date and time arithmetic 
  688.      Intro to set theory and relational algebra 
  689.      And more... 
  690.  
  691.  A lot of the material applies to other DB2/CS products (e.g.  DB2/6000).  A 
  692.  significant subset applies to any SQL implementation (DB2/MVS, Informix, 
  693.  Ingres, Oracle, Rdb, Sybase, etc). 
  694.  
  695.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  696.  
  697.  RexxBase Has Been Updated to Version 2.02 
  698.  
  699.   June 15, 1995
  700.   American Coders, Ltd
  701.   POB 97462
  702.   Raleigh, NC  27624  USA
  703.  
  704.  American Coders, LTD release an update to its shareware program RexxBase. 
  705.  RexxBase is a REXX API DLL that allows REXX programs to use dBase III and IV 
  706.  DBF, DBT, NDX and MDX files.  This update contains several bug fixes, program 
  707.  enhancements and documentation changes.  The newest release can be found in 
  708.  the file RXBAS202.ZIP. 
  709.  
  710.  The following is a list of the program changes. 
  711.  
  712.      Corrected documentation error.  RexxBase.SkipDeleted switches use YES or 
  713.       NO. 
  714.  
  715.      Corrected DLL to reflect documentation: RexxBase.dBaseFileType should be 
  716.       RexxBase.dBaseFileFormat.  Use RexxBase.dBaseFileFormat. 
  717.  
  718.      Corrected DLL to reflect documentation: RexxBase.dBaseFileType default 
  719.       value is "dbase3". 
  720.  
  721.      Improved GotoRecord function.  Specifically TOP parameter and indexes now 
  722.       in synch. 
  723.  
  724.      CREATE and PACKING functions failed for dBase IV memo fields. 
  725.  
  726.      Corrected documentation error.  References to 
  727.       RexxBase.AllowDuplicateIndex corrected to RexxBase.AllowDuplicateIndexes. 
  728.  
  729.      Corrected Reindex problem.  Not building control blocks correctly. 
  730.       Function required closing DBF before using again. 
  731.  
  732.      Patched Reindex function memory leak. 
  733.  
  734.      CreateDBFFrom function required closing source DBF before using again. 
  735.  
  736.      Restored CloseAllDBF to unregistered version. 
  737.  
  738.      Filter routines recalculated dates twice to produce incorrect 
  739.       results(rv). 
  740.  
  741.      REXXBASE.EXE concatenated INDEX filenames incorrectly. 
  742.  
  743.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  744.  
  745.  OS/2 USERS GROUP MEETINGS 
  746.  
  747.  [Editor's note - EDM/2 does not normally publish dates of SIG meetings, but 
  748.  these dates were posted well enough in advance and contain topics that deal 
  749.  with application development, so we made an exception by eliminating the non- 
  750.  relevant dates.] 
  751.  
  752.  New York, NY 
  753.  
  754.  Jul 17              Presentation Manager and Kernel API overview 
  755.  Aug 21              Intro to REXX + REXX and the Workplace Shell 
  756.  Sep 18              Debugging with IPMD 
  757.  Oct 16              C++ User Interface Class Library 
  758.  
  759.  All meetings will be held at the offices of the IBM Corporation 590 Madison 
  760.  Avenue in New York City, starting at 6 PM. 
  761.  
  762.  All are welcome. 
  763.  
  764.  Call the NYPC Voice BBS at 212-533-NYPC and enter menu code OST for last 
  765.  minute changes.  For other information call Bill Zack at 203-255-2979. 
  766.  
  767.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  768.  
  769.  Safetynet's StopLight is Now Available 
  770.  
  771.  Safetynet, Inc.  has made available for Internet downloading its StopLight for 
  772.  OS/2 security software.  StopLight for OS/2 goes far beyond Workplace Shell 
  773.  protection, and provides: 
  774.  
  775.      file and directory-level security (Read, Write, Create, Delete, Execute) 
  776.      for all OS/2 modes including PM, command prompt (OS/2 and DOS), dual 
  777.       boot, and Win-OS/2 
  778.      OS/2 2.x and OS/2 Warp compatibility 
  779.      unlimited users per workstation 
  780.      administrator and user security levels 
  781.      audit trail 
  782.      hard disk lock prevents booting from diskette to access the hard disk 
  783.      data encryption (USA version only) 
  784.      keyboard lock 
  785.      dual boot security for identical security when booting into DOS or OS/2 
  786.      much more... 
  787.  
  788.  The full product (without hard disk lock) is available for evaluation from our 
  789.  WWW and FTP sites.  If you need more information, please call our tech support 
  790.  department at 1- 800-OS2-SAFE or send e-mail to support@safe.net. 
  791.  
  792.   http://www.safe.net/safety/
  793.  
  794.   ftp://ftp.safe.net/pub/safetynet/
  795.  
  796.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  797.  
  798.  EDM/2 Now Distributed to BBS's in Denmark 
  799.  
  800.  EDM/2  announces the addition of Jesper Nielsen as a new network distributor. 
  801.  Jesper's responsibility is in the distribution of EDM/2 to various bulletin 
  802.  boards in Denmark.  Send email to afdata@pop02.ny.us.ibm.net for more 
  803.  information. 
  804.  
  805.  ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ 
  806.  
  807.  Comprehensive OS/2 TCP/IP application homepage 
  808.  
  809.  The TCP/IP applications list has been converted to HTML and moved.  It is 
  810.  available at http://wc62.residence.gatech.edu/sorensen/tcpip.html. 
  811.  
  812.  This page lists all known shareware/freeware/demoware TCP/IP applications for 
  813.  OS/2 and is catagorized.  It is updated based upon when hobbes.nmsu.edu cleans 
  814.  its /incoming directory. 
  815.  
  816.  Please e-mail any suggestions, additions, changes, etc.  to 
  817.  sorensen@wc62.residence.gatech.edu (or use the mailto: tag on the page).  The 
  818.  author is also on the IRC channel #OS/2 as No_one. 
  819.  
  820.  FYI - the text based version is outdated, and the wc51 server should no longer 
  821.  be considered stable. 
  822.  
  823.  
  824. ΓòÉΓòÉΓòÉ 5. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
  825.  
  826. How Do I Get EDM/2? 
  827.  
  828. EDM/2 can be obtained in any of the following ways: 
  829.  
  830. On the Internet 
  831.  
  832.      All back issues are available via anonymous FTP from the following sites: 
  833.  
  834.         -  hobbes.nmsu.edu in the /os2/newsltr directory. 
  835.         -  ftp.luth.se in the /pub/os2/programming/newsletter directory. 
  836.         -  generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory. 
  837.  
  838.      The EDM/2 mailing list.  Send an empty message to edm2-info@knex.mind.org 
  839.       to receive a file containing (among other things) instructions for 
  840.       subscribing to EDM/2.  This is a UUCP connection, so be patient please. 
  841.  
  842.      IBM's external gopher/WWW server in Almaden. The address is 
  843.       index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of 
  844.       the "OS/2 Information" menu; the URL is 
  845.       "gopher://index.almaden.ibm.com/1nonibm/os2nonib.70". 
  846.  
  847.  On Compuserve 
  848.  
  849.  All back issues are available in the OS/2 Developers Forum 2. 
  850.  
  851.  IBM Internal 
  852.  
  853.      IBM's internal gopher/WWW server in Almaden. The address is 
  854.       n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu; 
  855.       the URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70". 
  856.  
  857.  On BBS's 
  858.  
  859.      From BBS's in Denmark, send email to Jesper Nielsen at 
  860.       afdata@pop02.ny.us.ibm.net for a location near you. 
  861.  
  862.  How do I Get EDM/2? - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  863.  
  864.  
  865. ΓòÉΓòÉΓòÉ 6. C++ Compiler Review (Part 1) ΓòÉΓòÉΓòÉ
  866.  
  867.  
  868. ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
  869.  
  870. C++ Compiler Review (Part 1) 
  871.  
  872. Written by Gordon Zeglinski 
  873.  
  874. Introduction 
  875.  
  876. This issue kicks off our look at the various C/C++ compilers for OS/2.  We will 
  877. look at VisualAge C++, Watcom C/C++ 10a, Metaware High C/C++ 3.32 and hopefully 
  878. Borland C++ 2.0.  We start by giving an overview of the development environment 
  879. and the features of each compiler.  After we look at what each compiler has to 
  880. offer, we will compare the executables generated by each compiler (size and 
  881. speed) as well as the compile times for each compiler. These tests will consist 
  882. of compiling various OS/2 utilities (like unzip, zip, POVRay, sysbench, etc.), 
  883. a C++ test program, a Standardized Template Library (STL) example, and the 
  884. source code to AdeptXBBS. 
  885.  
  886. In this issue, we will look at Watcom C/C++ version 10 and IBM's Visual Age C++ 
  887. (C-Set++ 3.0). 
  888.  
  889. Before we start, I'll state my own compiler background.  For the last 2 years, 
  890. I have been using C-Set++ 2.x to develop OS/2 code.  I've become very familiar 
  891. with this environment, and invariably I will use it as the base to which I 
  892. formulate qualitative statements.  A review of C-Set++ 2.1 appeared in volume 
  893. 1, issue 5 of EDM/2. 
  894.  
  895. All the compilers will be run on a 486 DX2/66 MHz PC clone with 20M of RAM 
  896. running Warp Fullpack. 
  897.  
  898. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  899.  
  900.  
  901. ΓòÉΓòÉΓòÉ 6.2. Visual Age C++ for OS/2 version 3.0 ΓòÉΓòÉΓòÉ
  902.  
  903. Visual Age C++ for OS/2 version 3.0 
  904.  
  905. A full install of Visual Age C++ (VAC++) requires about 180M of disk space.  It 
  906. generates only 32-bit OS/2 programs.  This package is the successor to C-Set++ 
  907. version 2.1.  Thus, comparing it to C-Set++ 2.1 is natural. 
  908.  
  909. VAC++ has many new features over C-Set++ 2.1.  Officially they include: 
  910.  
  911.      Performance improvements in the compiler and linker 
  912.      Direct to SOM (DTS) support in the compiler 
  913.      New Class Browser 
  914.      Live Parsing Editor 
  915.      The Visual Builder - an object oriented graphical program code generator 
  916.      "Open Class Library" - allows C++ applications to be portable to multiple 
  917.       platforms (Unix, Power PC, Windows 32-bit, etc.)  when VisualAge becomes 
  918.       available for these platforms 
  919.      Database access classes 
  920.      Multimedia classes 
  921.      Workframe 3.0 
  922.  
  923.  Installation over C-Set++ 2.1 was somewhat of a pain.  The old copy of C-Set++ 
  924.  must be completely deleted and all references to it have to be removed from 
  925.  CONFIG.SYS.  The install uses the standard CID used by many new IBM products. 
  926.  Other than manually having to clean up the old install, it's a fairly simple 
  927.  installation.  The Warp toolkit, workframe, compiler and related tools are all 
  928.  installed at the same time.  Once you setup the install, it will successfully 
  929.  complete unattended.  Considering it takes about 30 minutes to install off a 
  930.  double speed CD drive, it's great being able to leave the machine alone and go 
  931.  do something useful.  One problem with the Warp toolkit is that it messes up 
  932.  the environment variables need by the SOM Developer's Toolkit (if you have 
  933.  this toolkit installed).  Some manual tweaking will be necessary to get the 
  934.  SOM toolkit working properly again. 
  935.  
  936.  C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  937.  
  938.  
  939. ΓòÉΓòÉΓòÉ 6.3. Compiler ΓòÉΓòÉΓòÉ
  940.  
  941. Compiler 
  942.  
  943. As in C-Set++ 2.1, the compiler needs a fair bit of RAM and is primarily disk 
  944. bound on this system.  The compiler is about 1.3 times slower compiling a large 
  945. C based project than C-Set++ 2.1.  Also the compiler seems to be more RAM 
  946. hungry as well.  However, the compiler is noticeably faster during the linking 
  947. of C++ code that uses templates.  In addition to the DTS support, the C runtime 
  948. library now has new functions that improve heap maintenance.  In addition to 
  949. multiple heaps, heap checking functions are now supported. POSIX locale's and 
  950. support functions have been added as well. 
  951.  
  952. I've run into several optimizer bugs while testing the compiler. Fortunately, 
  953. these bugs have been fixed in the compiler CSD that was recently released. 
  954. This CSD seems to reduce the compiler's memory consumption slightly as well.  I 
  955. still have one outstanding bug report with technical support:  calling 
  956. PrfOpenProfile() causing an access violation exception.  Migrating existing 
  957. applications to VAC++ may require a bit of work.  If you are packaging your own 
  958. copy of the C runtime library, you will need to redo the DEF file that controls 
  959. which functions you are exporting.  As well, the names of several libraries 
  960. have changed.  If you are explicitly linking to any of these libraries, you 
  961. will have to change their names in your makefiles. 
  962.  
  963. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  964.  
  965.  
  966. ΓòÉΓòÉΓòÉ 6.4. Development Environment ΓòÉΓòÉΓòÉ
  967.  
  968. Development Environment 
  969.  
  970. The Workframe/2 product has always been a flexible and easily extended 
  971. programming environment.  Version 3.0 is completely different than version 2.1. 
  972. It combines some some of the concepts of both Workframe 1.0 and 2.1 into a new 
  973. easy to understand package.  However, if you had used version 2.1, you will be 
  974. scratching your head for a while as you relearn how to do things.  (It will be 
  975. a long while, too.) 
  976.  
  977. Something weird is going on with the Workframe, too; everyone I've talked to 
  978. outside of IBM has significant performance problems.  For instance, pop-up 
  979. menus take seconds to appear, and anything involving filling in the project's 
  980. filenames takes almost half a minute to finish.  During this time, the CPU 
  981. usage goes way up and the system becomes sluggish.  One person inside IBM, who 
  982. is extremely knowledgeable about the inner's of the Workframe, has reported 
  983. performance levels that are FAR better than what I've seen. 
  984.  
  985. In addition to the performance problem, MAKEMAKE  doesn't always generate 
  986. makefiles that work.  I tried to migrate my WF version 2.1 projects to version 
  987. 3.0, but the process took too long and was awkward.  It was faster creating new 
  988. 3.0 projects from scratch. 
  989.  
  990. So, let's start by forgetting all we know about WF 2.1 and throwing away all 
  991. our previous projects.  How hard is it to get a project working?  Unlike 
  992. version 2.1, version 3.0 comes properly configured.  To start a new project, 
  993. you drag out and drop a copy of the project template.  Then, you open its 
  994. settings to configure the working directory, target, and the various build 
  995. parameters.  There are several great new features that should significantly 
  996. reduce the amount of time it takes to configure a new project or toggle a 
  997. project from "development mode" to "distribution mode".  In version 2.1 one had 
  998. to have multiple projects one for each mode.  This made it extremely awkward to 
  999. toggle a project's mode.  "Build Smarts" in version 3.0 makes this easy. 
  1000.  
  1001. Overall, version 3.0 is more stable and easy to start using than version 2.1. 
  1002. However, the performance problems and the faulty MAKEMAKE result in version 3.0 
  1003. being less useful than version 2.1. 
  1004.  
  1005. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1006.  
  1007.  
  1008. ΓòÉΓòÉΓòÉ 6.5. Debugger ΓòÉΓòÉΓòÉ
  1009.  
  1010. Debugger 
  1011.  
  1012. IPMD version 2.x (the debugger in C-Set++ 2.x) had been the OS/2 debugger to 
  1013. beat.  It has many features to aid in debugging PM and multi-threaded programs 
  1014. effectively.  Version 3.0 adds to this feature list but removes the "hierarchy 
  1015. browser".  (I always wondered why they put a C++ hierarchy browser in the 
  1016. debugger in the first place.  It merely duplicates some of the functionality in 
  1017. the browser.)  A quick summary of the new features include: 
  1018.  
  1019.      child process debugging - allows processes started by the debugged 
  1020.       program to be debugged. 
  1021.      exception filtering - allows the debugger to be configured to ignore 
  1022.       certain exceptions 
  1023.      SOM support - allows SOM classes to be monitored in the monitor windows. 
  1024.      Check heap when stopping - the debugger checks the heap when the program 
  1025.       stops executing (ie.  at a breakpoint or after a step command) 
  1026.      improved call stack now displays more information about the stack usage 
  1027.  
  1028.  The heap check function is particularly useful when searching for memory 
  1029.  corruption.  The strange thing, though, is that there isn't a way to check the 
  1030.  heap at any time.  The heap can only be automatically checked when the 
  1031.  debugged program has been stopped by the debugger.  The PM Message Spy and 
  1032.  Window Analysis functions are still present and have been redesigned to 
  1033.  improve functionality. 
  1034.  
  1035.  Overall, the debugger's feature set has been greatly improved.  However, it 
  1036.  has numerous bugs which make it less useful than the previous version. 
  1037.  Following is a brief list of problems I've encountered while moving 3 
  1038.  medium-to-large programs to VAC++: 
  1039.  
  1040.      in asynchronous debug mode, the debugger "looses control" of the PM 
  1041.       program.  It's as if the debugger can't terminate the debugged program. 
  1042.       Trying to "restart" the application results in the application being run 
  1043.       until the user terminates the application.  Once terminated, the debugger 
  1044.       "restarts" the application. 
  1045.  
  1046.      in syncronous mode, trying to step into (pressing "I") a function will 
  1047.       result in the debugger hanging. 
  1048.  
  1049.      after an access violation exception occurs in an OS/2 DLL, doing anything 
  1050.       other than continuing to execute the program can result in the debugger 
  1051.       soft hanging the system. 
  1052.  
  1053.      in syncronous mode, doing a lot of stepping over (pressing "O") can 
  1054.       result in hanging the debugger. 
  1055.  
  1056.      occasionally, when hitting a break point in thread 10 or 11 of the 
  1057.       program, the debugger crashes with an access violation in one of its 
  1058.       DLLs. 
  1059.  
  1060.  Note:  all of these bugs are reproducible in all 3 of the ported applications 
  1061.  while debugging multithreaded C or C++ PM code. 
  1062.  
  1063.  Because stepping into or over functions is a fundamental feature of a debugger 
  1064.  and the severity of the other bugs I found, I have to say that the debugger is 
  1065.  presently useless for PM programs.  I don't have any large text mode programs 
  1066.  to test the debugger on so it may very well work fine for these types of 
  1067.  applications. 
  1068.  
  1069.  C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1070.  
  1071.  
  1072. ΓòÉΓòÉΓòÉ 6.6. Browser ΓòÉΓòÉΓòÉ
  1073.  
  1074. Browser 
  1075.  
  1076. The browser now has support for SOM classes and has a new interface.  When 
  1077. running at 1280x1024, it would crash if I tried to open a graphical view. 
  1078. Reducing the resolution to 800x600 (used for the screen shots) allowed the 
  1079. graphical view to work.  A nice feature is that the file menu has options to 
  1080. load in the browser information for classes in the Open Class library; this 
  1081. makes the browser a good way to see how third party libraries are designed. 
  1082.  
  1083. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1084.  
  1085.  
  1086. ΓòÉΓòÉΓòÉ 6.7. Profiler ΓòÉΓòÉΓòÉ
  1087.  
  1088. Profiler 
  1089.  
  1090. The profiler in version 2.1 was an excellent tool for gathering information on 
  1091. how your program runs.  To profile the program it has to be compiled with 
  1092. profiling hooks inserted into the generated code by the compiler.  The hooks 
  1093. are used to inform the profiler when a function is called.  The result is that 
  1094. a highly accurate map of program execution can be generated, which can then be 
  1095. viewed in a multitude of ways to show time-based or calling-chain information. 
  1096.  
  1097. The major improvements to version 3.0 are support to trace up to 64 threads, 
  1098. trace runtime-loaded DLLs, and the ability to start and stop tracing any time 
  1099. during an applications execution.  The only problem with version 3.0 is that it 
  1100. crashes on startup. 
  1101.  
  1102. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1103.  
  1104.  
  1105. ΓòÉΓòÉΓòÉ 6.8. Visual Builder ΓòÉΓòÉΓòÉ
  1106.  
  1107. Visual Builder 
  1108.  
  1109. The visual builder is written in Smalltalk and it needs a lot of memory. Most 
  1110. people I talk to say to run the builder well, you need 32M of RAM.  I gave it a 
  1111. try on this system the HD was trashing a fair bit and the builder was sluggish, 
  1112. but it looked nice.  Its design is very object-oriented and fairly easy to pick 
  1113. up.  If it only would use less memory... 
  1114.  
  1115. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1116.  
  1117.  
  1118. ΓòÉΓòÉΓòÉ 6.9. Open Class Library ΓòÉΓòÉΓòÉ
  1119.  
  1120. Open Class Library 
  1121.  
  1122. The Open Class Library is designed to allow one's C++ code to be easily moved 
  1123. from one platform to another.  There is a price to pay for portability, though. 
  1124. The library is quite large and needs a fair bit of memory at runtime.  For 
  1125. small projects, it may be better to simply write the code to the raw API.  The 
  1126. class supports various objects to manipulate the user-interface, collection 
  1127. classes, and I/O streams.  The most notable improvements to the user interface 
  1128. support is the inclusion of toolbar support, 2-D graphics, animated buttons and 
  1129. flyover help.  Flyover help is textual information that appears by the mouse 
  1130. when the mouse is positioned over a button or toolbar element. 
  1131.  
  1132. Note:  a CSD for this component is available. 
  1133.  
  1134. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1135.  
  1136.  
  1137. ΓòÉΓòÉΓòÉ 6.10. Documentation ΓòÉΓòÉΓòÉ
  1138.  
  1139. Documentation 
  1140.  
  1141. As usual, the amount of paper documents is kept to a minimum.  All 
  1142. documentation is on-line in either INF or BOO format.  The INF documents have 
  1143. been refined over C-Set++ 2.1 in that they are now easier to use and search. 
  1144. For the paper junky, Postscript files are included. 
  1145.  
  1146. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1147.  
  1148.  
  1149. ΓòÉΓòÉΓòÉ 6.11. Summary ΓòÉΓòÉΓòÉ
  1150.  
  1151. Summary 
  1152.  
  1153. Within days of getting VAC++, a CSD for the compiler and Open Class library 
  1154. were available.  The compiler CSD lists the optimization bug I found while 
  1155. compiling unzip as fixed, but it did not fix the problem I have while calling 
  1156. PrfOpenProfile().  As a whole, this package has many excellent features, many 
  1157. of which should make code development much easier and faster.  Unfortunately, 
  1158. it presently has too many bugs to act as a replacement for large projects 
  1159. developed under C-Set++ 2.1. 
  1160.  
  1161. Given the C-Set++ team's track record with providing fixes for C-Set++ 2.1, 
  1162. though, I think that once we get a round of CSDs for all the components, this 
  1163. will be the  compiler package for OS/2.  It's likely that by the time a new 
  1164. project grows to the stage where the bugs I have found are important, there 
  1165. will be CSDs out to fix them. 
  1166.  
  1167. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1168.  
  1169.  
  1170. ΓòÉΓòÉΓòÉ 6.12. WATCOM C/C++ 10a ΓòÉΓòÉΓòÉ
  1171.  
  1172. WATCOM C/C++ 10a 
  1173.  
  1174. Watcom C/C++ 10a requires about 180M of disk space for a full installation. 
  1175. This includes support for: 
  1176.  
  1177.      16-bit development for the following platforms: 
  1178.  
  1179.         -  OS/2 1.x 
  1180.         -  DOS 
  1181.         -  Windows 3.x applications 
  1182.  
  1183.      32-bit development for the following platforms: 
  1184.  
  1185.         -  32-bit OS/2 2.x 
  1186.         -  extended DOS 
  1187.         -  Windows NT 
  1188.         -  Win32s 
  1189.         -  Win 3.x using a proprietary windows extender 
  1190.         -  Novell NLMs 
  1191.         -  Autocad ADS applications 
  1192.  
  1193.  [Editor's note - I believe it also supports QNX development.] 
  1194.  
  1195.  The package includes a multi-platform GUI and text mode debugger, a class 
  1196.  browser, a profiler, a GUI and text mode editor, a windows resource editor, 
  1197.  OS/2 2.1 toolkit, SOM 2.0 developers toolkit, and Microsoft's foundation 
  1198.  classes for Windows.  (Yes, the Windows development tools are richer than the 
  1199.  tools for OS/2 PM development.)  There are no message "spy" utilities, window 
  1200.  hierarchy utilities, etc. for PM development.  IBM's Developers Connection 
  1201.  CD's include basic applications that allow the developer to spy on messages, 
  1202.  etc.  Having PM-related debugging features integrated into the debugger is 
  1203.  advantageous when developing PM apps, though.  Also, the OS/2 version of the 
  1204.  text editor isn't PM based.  The biggest letdown with the package is that 
  1205.  there are more Windows utilities than OS/2 ones.  The main components of the 
  1206.  package, however, have native OS/2 support. 
  1207.  
  1208.  A complaint that I have is that the installation program needs to be polished. 
  1209.  While it is capable of copying the most of files to the HD, it only partially 
  1210.  configures the system.  It doesn't set the INCLUDE or LIB paths at all, 
  1211.  configure the DOS AUTOEXEC.BAT, or setup the Windows environments (when 
  1212.  installing Windows cross platform support).  Also, when running Warp you have 
  1213.  to edit the CONFIG.SYS after installing Watcom but before rebooting.  You must 
  1214.  move the ...\WATCOM\BINP\DLL;...\WATCOM\SOM\LIB  to the end  of your LIBPATH 
  1215.  otherwise the WPS will hang when you reboot due to a SOM version difference. 
  1216.  
  1217.  C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1218.  
  1219.  
  1220. ΓòÉΓòÉΓòÉ 6.13. Compiler ΓòÉΓòÉΓòÉ
  1221.  
  1222. Compiler 
  1223.  
  1224. The compiler is lean and mean.  Compile speed has been greatly improved over 
  1225. that of Watcom C/C++ 9.5.  In fact this compiler is now considerably faster 
  1226. than C-Set++ 2.1.  As with version 9.5, the compiler is easy on your HD because 
  1227. it is primarily CPU bound.  Thus, a faster CPU will have a dramatic effect on 
  1228. compilation time. 
  1229.  
  1230. The part I like the most about the compiler is its cross-platform capabilities. 
  1231. The 32-bit OS/2 compiler can generate code for any 32-bit target platform. 
  1232. Similarly, the 16-bit compiler can generate code for any 16-bit target 
  1233. platform.  In fact, I used the 16-bit OS/2 compiler to create a Windows 3.x 
  1234. 16-bit applications.  (If you have to write Windows programs you might as well 
  1235. use an OS/2 native development environment!)  Another bonus is that the package 
  1236. ships with an assembler.  Combining the 16-bit C/C++ compiler with the 
  1237. assembler, you have a great OS/2 device driver development environment. (It 
  1238. beats MSC 6.0 + MASM any day, in my opinion.) 
  1239.  
  1240. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1241.  
  1242.  
  1243. ΓòÉΓòÉΓòÉ 6.14. Development Environment ΓòÉΓòÉΓòÉ
  1244.  
  1245. Development Environment 
  1246.  
  1247. The IDE is somewhat similar to the Borland C++ IDE - it's easy to use and 
  1248. fairly intuitive.  Several targets can be grouped into a single project. 
  1249. However, the configuring the IDE is not straightforward.  I couldn't find any 
  1250. menus or documentation on how to add support for different tools into the IDE. 
  1251. By default, the IDE expects all C and C++ files to use the suffixes .C and .CPP 
  1252. respectively.  This is annoying if you want to distinguish between the "type" 
  1253. of C code.  An interesting feature, though, is that you can assign specific 
  1254. compiler switches to individual files.  Typically, IDE's only allow you to 
  1255. configure a set of swtiches for a given file type.  All .C files must then use 
  1256. the same switches.  This is not the case for the Watcom IDE. 
  1257.  
  1258. My biggest complaints about the IDE are that it can crash when you least want 
  1259. it to (usually right after making a lot of changes to the project), it uses EPM 
  1260. as its editor, and it needs a bit more polish.  Once it's polished up a bit and 
  1261. configuration is made easier it should be great. 
  1262.  
  1263. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1264.  
  1265.  
  1266. ΓòÉΓòÉΓòÉ 6.15. Debugger ΓòÉΓòÉΓòÉ
  1267.  
  1268. Debugger 
  1269.  
  1270. The debugger has both a PM and text mode version.  The PM version, though, is 
  1271. essentially the text mode debugger in PM version.  It lacks any PM-specific 
  1272. features and is rather plain.  A useful feature is that it can execute macros 
  1273. when a breakpoint is encountered.  Its biggest feature is that the OS/2 native 
  1274. debugger can be used to "remote" debug DOS and Windows programs.  This "remote" 
  1275. debugging can be performed on a networked machine or on the local machine. 
  1276. Unfortunately this feature doesn't work completely under Warp. 
  1277.  
  1278. Also, debugging multi-threaded programs under Warp needs a special command line 
  1279. switch (see http://www.watcom.on.ca for info).  These problems are supposed to 
  1280. be fixed in version 10.5, though.  The debug information can be stored in SYM 
  1281. files, giving you the advantage of not having to rebuild the executable to make 
  1282. a distributable form of your code. 
  1283.  
  1284. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1285.  
  1286.  
  1287. ΓòÉΓòÉΓòÉ 6.16. Browser ΓòÉΓòÉΓòÉ
  1288.  
  1289. Browser 
  1290.  
  1291. The browser lets you view inheritance information and the relationship between 
  1292. functions in a source file.  The biggest problem with the browser is that it 
  1293. includes all the structures and classes.  This can make it quite hard to find 
  1294. the class you are interested in, if you include <os2.h> or <windows.h>.  While 
  1295. you can selectively remove objects from the inheritance view, there is no way 
  1296. to remove or include all objects using criteria such as where they are defined, 
  1297. how they are defined, etc.  The result is that one often has to remove all the 
  1298. objects from the inheritance view and then add back those that one is 
  1299. interested in.  An editor can be launched from the browser to modify the source 
  1300. code.  (Note:  the IDE crashed while launching the editor, but I have not been 
  1301. able to reproduce this.) 
  1302.  
  1303. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1304.  
  1305.  
  1306. ΓòÉΓòÉΓòÉ 6.17. Profiler ΓòÉΓòÉΓòÉ
  1307.  
  1308. Profiler 
  1309.  
  1310. The profiler displays the data gathered by the sampler.  Unfortunately the 
  1311. sampler didn't work properly under Warp.  While trying to sample a 
  1312. multi-threaded PM application, the sampler would report an internal error when 
  1313. the sampled program terminated. 
  1314.  
  1315. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1316.  
  1317.  
  1318. ΓòÉΓòÉΓòÉ 6.18. Documentation ΓòÉΓòÉΓòÉ
  1319.  
  1320. Documentation 
  1321.  
  1322. The basic package includes compiler and tools on CD along with a getting 
  1323. started book.  The documentation package is extra.  It includes the following: 
  1324.  
  1325.      Watcom Graphical Tools User's Guide 
  1326.      Watcom Tools User Guide 
  1327.      Watcom C++ Class Library Reference 
  1328.      Watcom C/C++ User's Guide 
  1329.      Watcom C Library Reference 
  1330.      Watcom Linker User's Guide 
  1331.      Watcom Programmer's Guide 
  1332.      Watcom Debugger User's Guide 
  1333.      Watcom C Language Reference * 
  1334.      The C++ Programming Language, second Edition by Bjarne Stroustrup (see 
  1335.       note below). 
  1336.  
  1337.  Note:  Bjarne Stroustrup's book is not found in the online OS/2 documentation, 
  1338.  of course. 
  1339.  
  1340.  The book The C++ Programming Language is an excellent reference and is not 
  1341.  specific to the Watcom compiler.  The rest of the books are rather hard to 
  1342.  follow, though.  It's sometimes hard to find the information that deals with 
  1343.  the particular host and target environment you are using.  I suppose this is 
  1344.  the price one pays when the package supports so many target environments. 
  1345.  
  1346.  C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1347.  
  1348.  
  1349. ΓòÉΓòÉΓòÉ 6.19. Summary ΓòÉΓòÉΓòÉ
  1350.  
  1351. Summary 
  1352.  
  1353. The Watcom package allows one to make applications 16 and 32-bit applications 
  1354. for OS/2, DOS and Windows (NT, et al.) all from an OS/2-based environment.  The 
  1355. compiler generates very tight, fast code and does this relatively fast.  The 
  1356. incompatibilities it has with Warp should be taken care of in version 10.5.  In 
  1357. particular, this package - when combined with OS/2 - makes an excellent DOS and 
  1358. Windows development environment.  Its biggest weakness is the lack of any PM 
  1359. specific functions in its debugger, and its Warp incompatibilities. 
  1360.  
  1361. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1362.  
  1363.  
  1364. ΓòÉΓòÉΓòÉ 6.20. Wrapping Things Up ΓòÉΓòÉΓòÉ
  1365.  
  1366. Wrapping Things Up 
  1367.  
  1368. In this issue, we looked at Watcom C/C++ 10a and Visual Age C++ version 3.0. 
  1369. Watcom C/C++ 10.0 was written before the release of Warp. While its debugger 
  1370. and profiler have problems running under Warp, a new version of Watcom C/C++ 
  1371. has just been released which I am told is Warp-friendly.  Watcom C/C++ makes a 
  1372. good multi-platform compiler although it would be even better if it included 
  1373. some multi-platform GUI objects. 
  1374.  
  1375. Visual Age C++ comes with a class library designed for cross platform usage and 
  1376. a nice visual builder that utilizes this class library. The biggest problem 
  1377. with Visual Age C++ is that currently it is has too many bugs in its tools to 
  1378. be useful for handling large applications where a debugger and profiler may be 
  1379. needed. 
  1380.  
  1381. In the next issue we will look at the Metaware High C/C++ compiler and possibly 
  1382. Borland C/C++ for OS/2.  We will also see how well each compiler generates 
  1383. various C and C++ code, and test their C++ features. 
  1384.  
  1385. C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1386.  
  1387.  
  1388. ΓòÉΓòÉΓòÉ 7. Gearing Up For Games (Part 2) ΓòÉΓòÉΓòÉ
  1389.  
  1390.  
  1391. ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
  1392.  
  1393. Gearing Up For Games (Part 2) 
  1394.  
  1395. Written by Michael T. Duffy 
  1396.  
  1397. Introduction 
  1398.  
  1399. Welcome back to Gearing Up For Games.  Last time we looked into how to use DIVE 
  1400. to blit images to the screen, and then developed a canvas class to make 
  1401. accessing the DIVE buffer easier.  This time we will look at how palettes are 
  1402. handled under OS/2, and we will look at decoding and displaying the common 
  1403. bitmap format of PCX to our canvas object.  This article builds on the previous 
  1404. one, so the canvas class and DIVE code from the last article will be used in 
  1405. this (and future) articles.  Eventually all this code will go together to 
  1406. create a simple game, and the concepts will allow you to branch out and write 
  1407. more meaty games that run natively under OS/2.  So without further ado... 
  1408.  
  1409. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1410.  
  1411.  
  1412. ΓòÉΓòÉΓòÉ 7.2. Palettes ΓòÉΓòÉΓòÉ
  1413.  
  1414. Palettes 
  1415.  
  1416. Before I start my discussion of palettes, I must call attention to an article 
  1417. written for EDM/2 way back in issue 1-1.  Raja Thiagarajan wrote an unofficial 
  1418. guide to the palette manager, and I think it may have even been Raja who 
  1419. introduced me to EDM/2 in the first place (Thanks!). I would suggest that you 
  1420. read his article in addition to this one, because it covers some aspects of the 
  1421. palette manager which I will not touch on. 
  1422.  
  1423. I would also like to thank the many people on the Internet who helped me out 
  1424. when I was first learning about palettes.  Palettes under OS/2 drove me crazy 
  1425. for several months before I could finally control them to the point that they 
  1426. did what I wanted them to do.  Even now they occasionally surprise me; in 
  1427. preparing for this article I discovered that some of the palette code I had 
  1428. been using for a long time would only display a black window in 256 color mode, 
  1429. whereas it worked fine in the 32k color mode I normally use!  Just when I think 
  1430. I completely understand palettes, they surprise me with something like this. 
  1431.  
  1432. With the information in this article, the article in EDM/2 issue 1-1, and the 
  1433. API specifications in the manuals you should have enough information to 
  1434. experiment around with palettes.  The approach to palettes that I present here 
  1435. seems to work best for games that use DIVE, though there may be some subtle 
  1436. palette tricks that I am unaware of and thus don't cover. Palettes are tricky 
  1437. to use though, so be certain to approach any experimentation with lots of 
  1438. patience, otherwise you may well be driven insane. 
  1439.  
  1440. One final note before we begin:  This article makes the assumption that our 
  1441. application will display a 256 color image in our application's window, and use 
  1442. the DIVE API to do it.  DIVE is capable of displaying images with more than 256 
  1443. colors, but for simplicity's sake this series of articles will not cover those 
  1444. situations. 
  1445.  
  1446. What is a Palette? 
  1447.  
  1448. A palette is an array that tells PM what colors to use when displaying an 
  1449. image.  A 256 color bitmapped image has one byte for each pixel. This byte 
  1450. tells what color in which to display that pixel.  A palette is used to convert 
  1451. that byte into the color information the display hardware needs to actually put 
  1452. the color on the monitor.  Palettes can have up to 256 entries. Each entry 
  1453. describes one color, and the color information is stored in three bytes, one 
  1454. each for the component colors red, blue, and green.  As they are stored in 
  1455. bytes, each of these component colors can have a value ranging from 0 to 255. 
  1456. Using varying amounts of these three colors, any other color can be described. 
  1457. A bright red would have Red set to 255 and both Green and Blue set to zero. 
  1458. Black is achieved when all three are set to zero and white results from all 
  1459. three being set to 255. 
  1460.  
  1461. All palette activities for an OS/2 program are handled through the palette 
  1462. manager.  The palette manager is part of the OS/2 API, and is accessed through 
  1463. the API function calls.  A palette manager is needed in a GUI environment 
  1464. because multiple programs may be running at the same time and each program may 
  1465. require different color needs.  The palette manager tries it's best to meet 
  1466. these needs. 
  1467.  
  1468. However, the palette manager is restricted by hardware limitations.  Many 
  1469. common color modes of video cards have a maximum of being able to display 256 
  1470. colors at the same time.  Although each of these colors may be selected from 
  1471. among 262,144 colors (256k colors), on the graphics card there is a physical 
  1472. maximum of 256 color registers to hold the colors.  This has led to the 
  1473. development of two different kinds of palettes:  physical and logical. 
  1474.  
  1475. The physical palette is the palette set in these hardware registers.  Under 
  1476. OS/2, you can not set the physical palette directly.  The palette manager will 
  1477. always determine what colors go in the physical palette, and in what indices 
  1478. these colors are placed.  You can read the physical palette with 
  1479. GpiQueryRealColors(), but you cannot set it. 
  1480.  
  1481. [Note:  There is one exception to the above.  In dive.h a comment explains a 
  1482. way to set the physical palette with undocumented calls.  I would urge everyone 
  1483. to avoid this method though, since it is unknown what that code would do in a 
  1484. non-paletted video environment (such as the 32 and 64 bit modes), and this 
  1485. method may not be supported on different hardware (such as the PowerPC, or 
  1486. future Intel based hardware).  I have not experimented with the undocumented 
  1487. code in dive.h because of lack of information on the undocumented calls, and 
  1488. because I have been able to achieve the results I need through the palette 
  1489. manager and without messing up the integrity of the desktop.] 
  1490.  
  1491. Although programs cannot access the physical palettes, they can have their own 
  1492. logical palettes.  A logical palette is set up in the same format as a physical 
  1493. palette.  The logical palette is sent to the palette manager, and whenever your 
  1494. window has focus, the palette manager will change the physical palette to match 
  1495. the logical palette as much as possible.  For the colors that do not match the 
  1496. physical palette exactly, the palette manager will decide the closest match, 
  1497. and use that instead.  When you request that color 4 be drawn to the screen, 
  1498. the palette manager will look at color 4 in the logical palette, decide what 
  1499. color it most closely matches in the physical palette, and send the new color 
  1500. out to the display hardware. 
  1501.  
  1502. By approaching palettes this way, several applications can share the scarce 
  1503. palette entries at the same time.  The palette manager will always try and 
  1504. fulfill the needs of the palette in the active window.  Applications whose 
  1505. windows are not active will still have their colors remapped to the closest 
  1506. palette entry, but the palette manager will not use the inactive palettes to 
  1507. determine the contents of the physical palette.  Note that remapping is done 
  1508. when an image is drawn to the screen, such as with DiveBlitImage().  If the 
  1509. display is in a 256 color mode, the physical palette changes, and a window is 
  1510. not redrawn, then its colors will be wrong. 
  1511.  
  1512. But what about graphics modes with more than 256 colors?  Many users of OS/2 
  1513. have their displays set to modes that offer 32k, 64k, or even 16.4 million 
  1514. colors.  In these cases, there are no color registers to fill.  If two 
  1515. applications request palettes of 256 different colors each, both requests can 
  1516. be met without any problem.  In these cases there is no physical palette to 
  1517. set, but a logical palette is still required.  The system must know what color 
  1518. each of the 256 palette entries in our source bitmap is to be displayed as when 
  1519. it converts each pixel to a 15, 16, or 24 bit color value. 
  1520.  
  1521. How to Use Palettes Under OS/2 
  1522.  
  1523. Our goal is to use palettes in conjunction with the DIVE API in order to 
  1524. display images in a window.  Although DIVE has the calls DiveSetSourcePalette() 
  1525. and DiveSetDestinationPalette(), neither of these calls affects the physical 
  1526. palette in any way.  These calls are used to tell DIVE what logical palette it 
  1527. is mapping from and what physical palette it is mapping to.  To change the 
  1528. physical palette in 256 color video modes, you must request that the palette 
  1529. manager remap the physical palette as much as possible to a specified logical 
  1530. palette. 
  1531.  
  1532. The steps for the creation and activation of a palette are as follows: 
  1533.  
  1534.    1. Query the device context of your client window with WinOpenWindowDC(). 
  1535.  
  1536.    2. Create a presentation space from the device context with GpiCreatePS(). 
  1537.       You cannot use a cached-micro PS (from WinGetPS()). We will use a micro 
  1538.       PS. 
  1539.  
  1540.    3. Create an array that describes your palette.  (The format for this array 
  1541.       is described below.)  Use the PC_RESERVED flag to obtain as many of your 
  1542.       colors as possible. 
  1543.  
  1544.    4. Create an OS/2 palette from this array and obtain a handle to the new 
  1545.       palette with GpiCreatePalette(). 
  1546.  
  1547.    5. Select the palette into the presentation space with GpiSelectPalette(). 
  1548.  
  1549.    6. Make the palette active ("realize it") with WinRealizePalette(). 
  1550.  
  1551.    7. Set the palette DIVE will use for your source bitmap by using your 
  1552.       original array with DiveSetSourcePalette(). 
  1553.  
  1554.    8. Tell DIVE what the physical palette is by either using 
  1555.       GpiQueryRealColors() and passing the result to 
  1556.       DiveSetDestinationPalette(), or call 
  1557.       DiveSetDestinationPalette(hDive,0,256,0). 
  1558.  
  1559.    9. Blit your image. 
  1560.  
  1561.       During normal processing you have a few tasks to perform to maintain the 
  1562.       palette. 
  1563.  
  1564.   10. On WM_REALIZEPALETTE messages, inform DIVE that the physical palette may 
  1565.       have changed.  Do this with either method described in step 8, though 
  1566.       simply calling DiveSetDestinationPalette(hDive,0,256,0) is the easiest. 
  1567.  
  1568.   11. On a WM_ACTIVATE message, if your application is losing focus, free up 
  1569.       your palette so that other applications may have as many of their colors 
  1570.       mapped into the physical palette as possible.  Do this by selecting a 
  1571.       null palette into the presentation space with GpiSelectPalette(), and 
  1572.       activate this null palette with WinRealizePalette(). 
  1573.  
  1574.   12. On a WM_ACTIVATE message, if your application is gaining focus select and 
  1575.       activate your desired palette again so that the physical palette will be 
  1576.       remapped more closely to your logical one.  Use GpiSelectPalette() and 
  1577.       WinRealizePalette() to achieve this. 
  1578.  
  1579.       When you are done using the palette and your game is ready to end. 
  1580.  
  1581.   13. De-select your palette from the presentation space by selecting a null 
  1582.       palette with GpiSelectPalette(). 
  1583.  
  1584.   14. Destroy the palette with GpiDeletePalette(). 
  1585.  
  1586.   15. Destroy the presentation space with GpiDestroyPS(). 
  1587.  
  1588.  Notes 
  1589.  
  1590.  Certain things must be considered in each of the above steps.  The important 
  1591.  ones are detailed below, and the general implementation of the steps can be 
  1592.  viewed in the included sample files game2.cpp and os2pal.cpp. 
  1593.  
  1594.  Step 1:  WinOpenWindowDC() will only work once per window. Multiple calls will 
  1595.  fail, so be certain to save the returned device context handle. 
  1596.  
  1597.  Step 2:  again, make certain that you do not use a cached micro PS. For our 
  1598.  purposes, we will call GpiCreatePS() with the flags PU_PELS, GPIF_DEFAULT, 
  1599.  GPIT_MICRO, and GPIA_ASSOC. Also, be certain to save the handle to this 
  1600.  presentation space and use it throughout your program.  This includes using it 
  1601.  with the DIVE code that calls GpiCreateRegion(), GpiQueryRegionRects(), and 
  1602.  GpiDestroyRegion().  If you create and use separate PSs for palette and DIVE 
  1603.  tasks, then in 256 color video modes your blitted images will appear black, 
  1604.  even though they will blit correctly in higher color resolution modes. 
  1605.  
  1606.  Step 3:  the array that describes your palette is an array of unsigned longs. 
  1607.  Three of the bytes in the ULONG describe the red, blue, and green components 
  1608.  of the color, and the fourth byte is a flag byte.  The flag byte tells the 
  1609.  palette manager a bit more information about that specific color.  For our 
  1610.  purposes, we will set all of the flags to the same value. This value is 
  1611.  PC_RESERVED, and it signals the palette manager that the color in question may 
  1612.  change frequently due to palette animation. Therefore the palette manger will 
  1613.  not use these colors for other windows, and you have more control over what 
  1614.  colors are put in the physical palette while your window has focus. 
  1615.  
  1616.  The formula for placing the four component bytes into a ULONG is: 
  1617.  
  1618.   ulArrayEntry = ((ULONG)byFlag << 24) + ((ULONG)byRed << 16) + ((ULONG)byGreen << 8) + byBlue;
  1619.  
  1620.  [Editor's note - you can also use the RGB2 structure for this purpose.] 
  1621.  
  1622.  Step 4:  with GpiCreatePalette(), for flOptions we use LCOL_PURECOLOR to 
  1623.  prevent dithering, but we do not use LCOL_OVERRIDE_DEFAULT_COLORS in order to 
  1624.  keep from messing up the desktop colors.  For ulFormat we use LCOLF_CONSECRGB 
  1625.  as it is currently the only supported format.  We pass this function an array 
  1626.  of the format described in step 3 above. 
  1627.  
  1628.  Step 5:  presentation spaces are used to hold display information for a 
  1629.  window.  If we were to use Gpi drawing routines, the PS would hold the current 
  1630.  drawing colors, line characteristics, marker styles, character attributes, and 
  1631.  so on.  The PS also holds palette information for our window. To tell the PS 
  1632.  which palette to use, we call GpiSelectPalette(). 
  1633.  
  1634.  Step 6:  even though we selected a palette to use for our PS in step 5, this 
  1635.  palette is not yet made active.  In order to tell the system to use our 
  1636.  palette whenever our window has focus, we must call WinRealizePalette(). 
  1637.  
  1638.  Step 7:  we must tell DIVE which color each byte in our DIVE buffer stands 
  1639.  for.  This is done with DiveSetSourcePalette().  If DiveSetSourcePalette() is 
  1640.  not called, then the default palette is used.  If your DIVE buffer does not 
  1641.  use the default palette, your results will be unpredictable. 
  1642.  
  1643.  Step 8:  we must also tell DIVE about the colors of the display hardware. 
  1644.  This can be done by retrieving the physical palette with GpiQueryRealColors() 
  1645.  and passing it to DiveSetDestinationPalette().  A shortcut to this is to call 
  1646.  DiveSetDestinationPalette() with a null pointer to the palette array.  This 
  1647.  will instruct the routine to call GpiQueryRealColors() on its own.  The notes 
  1648.  for this step also apply to step 10 and the WM_REALIZEPALETTE message. 
  1649.  
  1650.  Steps 11 and 12:  When our game loses focus, one of the things we want to do 
  1651.  is give the system back as many colors as possible so that other applications 
  1652.  may use them.  Since we use the PC_RESERVED flag with all colors of our game's 
  1653.  palettes, our palette holds a lot of weight with the palette manager.  By 
  1654.  deactivating our palette when we lose focus, the window receiving focus will 
  1655.  have its colors more readily remapped into the physical palette.  By 
  1656.  specifically reactivating our palette when we regain focus, our colors are set 
  1657.  in the physical palette without delay.  We need to redraw our window when we 
  1658.  regain focus in case we received focus when another overlapping window closed. 
  1659.  Such situations lead to a corrupted display if we don't redraw our window.  In 
  1660.  the future when we have a blit thread continually drawing our image to the 
  1661.  window, the explicit redraw will not be needed. 
  1662.  
  1663.  Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1664.  
  1665.  
  1666. ΓòÉΓòÉΓòÉ 7.3. The OS2Palette object ΓòÉΓòÉΓòÉ
  1667.  
  1668. The OS2Palette object 
  1669.  
  1670. Many of the above steps can be combined because they always occur after one 
  1671. another, such as GpiSelectPalette() and WinRealizePalette().  Also, we may have 
  1672. to work with palettes other than OS/2 palettes.  An example of this are the 
  1673. palettes stored in compressed bitmap files.  To simplify palette operations we 
  1674. will use a palette object that hides from us repetitive tasks.  For learning 
  1675. about the specific implementation of any of the tasks provided by the palette 
  1676. object, I encourage you to look at the source code for the object in 
  1677. os2pal.cpp. 
  1678.  
  1679. The following functions are those provided by the OS2Palette object.  They do 
  1680. not cover every single aspect of palettes, but they provide an illustration of 
  1681. the major points.  Also, they provide all the functionality we need for our 
  1682. simple game. 
  1683.  
  1684. Default16():  sets the palette to the first 16 colors of a standard VGA 
  1685. palette.  This can be done for initialization and testing purposes.  This 
  1686. function illustrates how to organize and set a default palette. 
  1687.  
  1688. Convert():  this routine converts the internal palette from one format to 
  1689. another.  The two formats implemented in this code are for plain 8-bit RGB 
  1690. palettes and OS/2 palettes.  The former are what you might find in a compressed 
  1691. bitmap (we will use them in the PCX codec), and the latter are what you will 
  1692. pass to OS/2 and DIVE. 
  1693.  
  1694. InitSystemPalette():  this will convert the internal palette to the OS/2 
  1695. format, create an OS/2 palette, select it into the supplied presentation space, 
  1696. and realize it. 
  1697.  
  1698. UninitSystemPalette():  this will de-select the internal palette from the 
  1699. presentation space, realize a null palette, and destroy the palette.  This 
  1700. routine is called on cleanup. 
  1701.  
  1702. SuspendSystemPalette():  this will de-select the palette from the presentation 
  1703. space and realize a null palette, but it will not destroy the palette.  This is 
  1704. meant to be used on a WM_ACTIVATE message. Call RestoreSystemPalette() to 
  1705. reactivate the palette. 
  1706.  
  1707. RestoreSystemPalette():  restores the palette suspended by 
  1708. SuspendSystemPalette(). 
  1709.  
  1710. SetAsDiveSource() and SetAsDiveDestination(): these routines are used to tell 
  1711. DIVE about the palette.  You will usually have at least two palette objects, 
  1712. one for the DIVE bitmap and one for the screen. If you choose to always set the 
  1713. DIVE destination palette with DiveSetDestinationPalette(hDive,0,256,0), then a 
  1714. palette for the screen is not needed. 
  1715.  
  1716. LoadActualPalette():  this sets the palette to the physical palette. 
  1717.  
  1718. SetValuesFromRaw8():  this will set a range of values from an array of 8-bit 
  1719. RGB values. 
  1720.  
  1721. PaletteFromBlock(), RequestSaveBlock(), and ReleaseSaveBlock():  these three 
  1722. functions package or unpackage a palette into a single block of data.  These 
  1723. routines will be used in the future when we look at storing data in a single 
  1724. library file. Currently they may be used to load and save a palette to disk. 
  1725.  
  1726. SetFlag() and QueryFlag():  these inline functions are for setting and getting 
  1727. the value that is copied into the flag position of the colors in an OS/2 format 
  1728. palette. 
  1729.  
  1730. QueryPaletteArray():  this returns a pointer to the internal array that 
  1731. contains the palette.  The format of the array depends on the format set with 
  1732. Convert().  One use of this routine would be to supply palette information to a 
  1733. bitmap encoding routine.  First, Convert()  would be used to set an 8-bit 
  1734. palette.  Then this routine would be used to get a pointer to the palette 
  1735. information to send to the encoding routine. 
  1736.  
  1737. QueryLastErrorCode():  Returns the code of the last error that occurred.  This 
  1738. error code is specified in errcodes.hpp and the associated message is stored in 
  1739. game2.msg.  This error code can be used with PostError(), a routine found in 
  1740. errdisp.cpp. 
  1741.  
  1742. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1743.  
  1744.  
  1745. ΓòÉΓòÉΓòÉ 7.4. Palettes for Multiple Child Windows ΓòÉΓòÉΓòÉ
  1746.  
  1747. Palettes for Multiple Child Windows 
  1748.  
  1749. Sometimes I am very glad that I don't keep a rocket launcher on hand near my 
  1750. computer.  Recently I'm afraid that I would have had to blow my computer into 
  1751. tiny, unrecognizable pieces considering how much grief it caused me. After 
  1752. months of being bothered by the same, nagging palette problem, I finally 
  1753. discovered a solution. 
  1754.  
  1755. The problem arises when you have two child windows, both of which are using 
  1756. DIVE to blit an image to its client area.  I ran across this situation while I 
  1757. was writing editors and other utilities for my own game, though such a 
  1758. situation could very well arise in a game with multiple windows. 
  1759.  
  1760. In order to get the same palette to display correctly in both windows, 
  1761. implement a palette as above in the "How To Use Palettes in OS/2" section. The 
  1762. various steps will be split amongst the parent and children windows as follows: 
  1763.  
  1764.    1. The HDC and the HPS for the palette should be derived from the parent 
  1765.       window.  The palette should be created, selected, realized, and 
  1766.       eventually destroyed from the parent window.  The parent window will 
  1767.       handle suspending and restoring the system palette on WM_ACTIVATE calls. 
  1768.  
  1769.    2. An HDC and HPS should also be created for each child window, and these 
  1770.       handles will be used to setup the DIVE blitter among other things.  No 
  1771.       palettes will be selected into the child windows' HPS's, however. 
  1772.  
  1773.    3. Each child window should have its own instance of DIVE. 
  1774.  
  1775.    4. Instead of setting the DIVE source and destination palettes in the parent 
  1776.       window, send messages to the child windows and have them perform these 
  1777.       tasks. When you send the message, pass a pointer to the palette array as 
  1778.       one of your parameters.  Make sure this array is in the OS/2 palette 
  1779.       format. 
  1780.  
  1781.    5. Do not use the shortcut of DiveSetDestinationPalette(hDive,0,256,0).  You 
  1782.       will have to use GpiQueryRealColors(), and then pass a pointer to the 
  1783.       returned palette array to each of the child windows so that they can call 
  1784.       DiveSetDestinationPalette() with this info.  When you need to update the 
  1785.       destination palette, only call GpiQueryRealColors() once and pass the 
  1786.       same array to both child windows.  Every time the parent window receives 
  1787.       a WM_REALIZEPALETTE message, it must query the real palette and pass the 
  1788.       array to each of the child windows.  The child windows should not process 
  1789.       the WM_REALIZEPALETTE message. 
  1790.  
  1791.  Performing the above steps should allow the same palette to be used for two 
  1792.  separate child windows. 
  1793.  
  1794.  Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1795.  
  1796.  
  1797. ΓòÉΓòÉΓòÉ 7.5. Graphics Formats ΓòÉΓòÉΓòÉ
  1798.  
  1799. Graphics Formats 
  1800.  
  1801. When graphics are stored to disk, they are usually saved in a special format 
  1802. rather than just dumping memory to a disk file.  These formats contain 
  1803. additional information about the graphic such as its size, number of colors, 
  1804. palettes, and other types of info.  The graphic data is also usually compressed 
  1805. in order to save disk space.  Compression/decompression algorithms are usually 
  1806. called codec's, and each graphic format usually has it's own codec which is 
  1807. different from the others.  Codecs differ in their compression ratio, speed, 
  1808. and quality.  Certain codecs throw out some of the original information during 
  1809. compression, and then try and guess what is missing when they decompress the 
  1810. image.  These are called lossy codecs because they lose some of the data.  JPEG 
  1811. is an example of a format with a lossy codec.  Lossless codecs generate the 
  1812. same image upon decompression as was given to them for compression.  Popular 
  1813. formats with lossless codecs include GIF, PCX, TIF, and PNG. 
  1814.  
  1815. Our code will deal with PCX files.  PCX files have the advantage of being 
  1816. supported natively by many paint programs both shareware and commercial.  This 
  1817. format was originally developed by ZSoft for their paint program PC Paintbrush, 
  1818. but it was adopted by many other programs as well due to its ease of use.  PCX 
  1819. files support monochrome, 16-color, and 256 color images though we will only 
  1820. concern ourselves with the monochrome and 256 color capabilities.  PCX files 
  1821. are also good because their compression scheme is very simple to understand. 
  1822. It is not a compression scheme that works well for all graphics though, and 
  1823. many scanned images would wind up larger than where they started if the PCX 
  1824. scheme were used on them.  Nevertheless, it will suit our needs nicely. 
  1825.  
  1826. As far as implementation in our sample code is concerned, the PCX 
  1827. encoding/decoding object is derived from a parent class called BitmapPainter. 
  1828. This allows us to treat different graphic formats in the same way.  The same 
  1829. calls are used to setup, compress, and decompress graphics no matter what 
  1830. format in which they are stored.  Although we will only implement code to deal 
  1831. with PCX files, you could write code to support other formats without having to 
  1832. change much code in programs that already use BitmapPainter-derived objects. 
  1833.  
  1834. Also, our PCX display code will use the Canvas class to hold the decompressed 
  1835. image.  The Canvas class was covered in the first article of this series. 
  1836.  
  1837. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  1838.  
  1839.  
  1840. ΓòÉΓòÉΓòÉ 7.6. On to PCX! ΓòÉΓòÉΓòÉ
  1841.  
  1842. On to PCX! 
  1843.  
  1844. PCX files have three parts:  the header, the image data, and the palette. 
  1845. Monochrome images only have a header and the image data, since all pixels are 
  1846. either black or white. 
  1847.  
  1848. The Header 
  1849.  
  1850. The header of the PCX looks like this: 
  1851.  
  1852. typedef struct {
  1853.    BYTE    byManufacturer;     // always 0x0a
  1854.    BYTE    byVersion;          // version number
  1855.    BYTE    byEncoding;         // always 1
  1856.    BYTE    byBitsPerPixel;     // color bit depth
  1857.    USHORT  usXmin;             // coordinate of left side of image
  1858.    USHORT  usYmin;             // coordinate of top of image
  1859.    USHORT  usXmax;             // coordinate of right side of image
  1860.    USHORT  usYmax;             // coordinate of bottom of image
  1861.    USHORT  usHres;             // horizontal resolution of creation device
  1862.    USHORT  usVres;             // vertical resolution of creation device
  1863.    BYTE    abyPalette [48];    // color palette for 16 color images
  1864.    BYTE    byReserved;
  1865.    BYTE    byColorPlanes;      // number of color planes in the image
  1866.    USHORT  usBytesPerLine;     // line buffer size
  1867.    USHORT  usPaletteType;      // gray or color palette
  1868.    BYTE    abyFiller [58];
  1869. } PCXHEADER;
  1870.  
  1871. The header is exactly 128 bytes long, and is always located at the very 
  1872. beginning of a PCX file.  A more detailed meaning of each field is as follows: 
  1873.  
  1874. Manufacturer:  always 0x0a.  Checking this byte is the only way to really tell 
  1875. whether or not a file is a PCX file. 
  1876.  
  1877. Version:  this variable is meant to tell what version of PC Paintbrush created 
  1878. the file.  A zero indicated PC Paintbrush version 2.5.  A two or three 
  1879. signifies version 2.8.  A two means that the abyPalette field contains palette 
  1880. information whereas a three means that the image is either monochrome or meant 
  1881. to be displayed with the default palette of the device.  A five indicates that 
  1882. the PCX came from version 3.0 or better, and this is the only version that can 
  1883. support 256 color images. 
  1884.  
  1885. Encoding:  this is always 1, though the field was put here in case ZSoft wanted 
  1886. to add a different kind of codec to the PCX specification.  A 1 signifies that 
  1887. the image uses a Run- Length Encoding (RLE) codec. 
  1888.  
  1889. BitsPerPixel:  this tells how many bits are used to make a single pixel in a 
  1890. single color plane.  Monochrome images only have black and white pixels, so 
  1891. they have 1 bit per pixel.  256 color images have 8 bits per pixel since they 
  1892. need entries from 0 to 255.  16 color images need 4 bits to generate a number 
  1893. between 0 and 15.  However, 16 color images are stored in four color planes, so 
  1894. they only have one bit per pixel in each color plane. Monochrome and 256 color 
  1895. images only have a single color plane, so their bits per pixel value is a count 
  1896. of their total bits.  Color planes are explained below. 
  1897.  
  1898. Xmin, Ymin, Xmax, and Ymax:  these values give the boundaries of the image. 
  1899. Usually Xmin and Ymin will be equal to zero.  These coordinates represent the 
  1900. origin, and the origin is located in the top left hand corner of the image. 
  1901. Xmax and Ymax give the right and bottom edges respectively.  These coordinates 
  1902. are inclusive.  This means that if Xmin is 0 and Xmax is 639, a row of this 
  1903. image runs from pixel 0 to pixel 639 inclusive.  It has a width of 640 pixels. 
  1904. Therefore when computing the width or the height from these values, be certain 
  1905. to add 1 to get the correct answer:  (i.e.  usWidth = usXmax - usXmin + 1). 
  1906.  
  1907. Hres and Vres:  these values give the dimensions of the hardware that generated 
  1908. the image, and are basically useless values. 
  1909.  
  1910. Palette:  this array of bytes contains a palette for 16 color images. PCX 
  1911. palette have a red, blue, and green byte for each color, so 3 color bytes times 
  1912. 16 colors leads to the 48 byte length of this array.  The PCX format was 
  1913. developed before 256 color images were available on the PC.  As a result, the 
  1914. designers of the PCX format did not leave room for a 256 color palette.  To 
  1915. solve this problem, the palette for 256 color images was tacked onto the end of 
  1916. the PCX file, and this array was not used.  Since we will not be using 16 color 
  1917. images, we will ignore this field. 
  1918.  
  1919. ColorPlanes:  this tells how many color planes are used for the image.  Color 
  1920. planes are used because of the way hardware is setup in EGA and VGA cards for 
  1921. the 4 and 16 color modes.  A pixel in these modes has one bit in each bit plane 
  1922. instead of having its bits side by side as in 256 color mode. The bits in each 
  1923. of the bit planes are combined to get the color index of a single pixel.  If 
  1924. you haven't encountered bit planes before and don't understand how they are set 
  1925. up, I would suggest looking in a book on EGA/VGA cards.  They take a little bit 
  1926. of time and space to explain clearly, and since we are not dealing with 16 
  1927. color formats I will not cover them here. 
  1928.  
  1929. BytesPerLine:  this field tells how many bytes are in a single decompressed 
  1930. row.  This is useful in monochrome and 16 color images, but the bytes per line 
  1931. in a 256 color image is the same as its width. 
  1932.  
  1933. PaletteType:  this simply tells whether or not an image is meant to be 
  1934. displayed in color or gray scale.  A value of 1 indicates gray scale and a 
  1935. value of 2 indicates color. 
  1936.  
  1937. The Codec 
  1938.  
  1939. The algorithm for decoding a PCX image is simple.  You take the current byte of 
  1940. the image data and look at it's top two bits.  If they are both clear, then you 
  1941. write that byte out to your canvas.  If they are both set, you clear them and 
  1942. that byte becomes your duplication count, or run length.  Take the next byte 
  1943. and copy it to the canvas "run length" number of times.  Repeat the process 
  1944. until you have enough bytes to fill a row.  Move to the next row down and 
  1945. repeat the process for that row.  Do this until there are no more rows left in 
  1946. the image. 
  1947.  
  1948. The only catch to the above algorithm is when you run across a single pixel 
  1949. that has information in one or both of the top two bits.  Bytes for these types 
  1950. of pixels are handled as having a run length of 1, since the entire 8 bits of 
  1951. the byte can be stored in the byte following the run length byte. 
  1952.  
  1953. Encoding a PCX is just the reverse of this process.  Start at the first pixel 
  1954. in the top row of your image.  Count how many times this pixel color appears in 
  1955. a run.  Do not let this run length go over 63, because you can only store the 
  1956. run length in 6 bits (the top two will be set).  If the run of bytes is greater 
  1957. than one, set the top two bits of the run length and send it to your encode 
  1958. buffer.  Next send the byte to duplicate.  If there is only one byte, check and 
  1959. see if any of the top two bits are set.  If one or both are set, output a run 
  1960. length of one, and then output the byte.  Otherwise, simply output the byte. 
  1961. Repeat until you are done with a row, and then move to the next row down. 
  1962. Continue in this way until all rows are done. 
  1963.  
  1964. This same codec is used in both monochrome and 256 color images, though the 
  1965. pixels are stored slightly differently.  For monochrome images, each byte 
  1966. contains 8 pixels, since only one bit is needed for each pixel.  If the bit is 
  1967. set, it denotes a white pixel.  If it is clear, it denotes a black pixel.  The 
  1968. most significant bit is the left most pixel in that byte, and the least 
  1969. significant pixel is to the right.  Bits can be tested in the byte with a 
  1970. bitwise "and" operation. 
  1971.  
  1972. 256 color images have their bits stored right next to each other.  Since it 
  1973. takes 8 bits per pixel, the entire byte is used for the color index.  You can 
  1974. decode the row directly onto the surface of a Canvas. 
  1975.  
  1976. The Palette 
  1977.  
  1978. In monochrome images, there is no palette because the pixels can either be 
  1979. white or black.  In 256 color images, the palette is attached to the end of the 
  1980. PCX file.  The palette is stored as one byte each for the red, green, and blue 
  1981. components of each color, in that order (RGB).  There are 256 colors possible, 
  1982. so the palette is 3 color bytes * 256 indexes = 768 bytes long.  To make sure 
  1983. that you aren't reading image data instead of palette data, PCX files have the 
  1984. byte 0x0c right before the palette information starts. 
  1985.  
  1986. To read a PCX palette you find the end of the file and move back 769 bytes. 
  1987. Check that byte to see if it equals 0x0c.  If it does, read the next 768 bytes 
  1988. as your palette. 
  1989.  
  1990. Byte Order 
  1991.  
  1992. One last note about palettes:  To use the palette attached to the PCX file, you 
  1993. will need to convert it to an OS/2 palette.  An OS/2 palette has the elements 
  1994. Flag-Red-Green-Blue stored in a ULONG.  However, Intel based PCs store USHORTs 
  1995. and ULONGs in a byte reversed order, and if you access the OS/2 palette as an 
  1996. array of bytes instead of an array of ULONGs, then you must take this into 
  1997. consideration. 
  1998.  
  1999. The byte reversal scheme works like this:  Suppose you have a variable at 
  2000. memory location 0x1000.  A byte would be stored at location 0x1000, a USHORT 
  2001. would be in locations 0x1000 and 0x1001, and a ULONG would be stored in 
  2002. locations 0x1000 through 0x1003.  Placing a byte is no problem; just put it in 
  2003. location 0x1000.  A USHORT is made up of two bytes.  One byte handles the 
  2004. lowest 8 bits, and the other byte handles the highest 8-bits. When an Intel 
  2005. based PC stores the USHORT in memory, it will place the lowest 8 bits in the 
  2006. first byte (0x1000), and the highest 8 bytes in the next byte (0x1001). 
  2007.  
  2008. A number under 256, say the value 42, would be stored in the lowest 8 bits of 
  2009. the USHORT.  A pointer to our USHORT would have the value of 0x1000.  When the 
  2010. USHORT is accessed with the pointer, then the bytes will be placed in their 
  2011. correct order so that the value of 42 is retrieved.  However, what if we 
  2012. typecast this pointer and use it as a pointer to type BYTE.  A BYTE can hold 
  2013. the value of 42, but it is only looking for a single byte in memory (8-bits). 
  2014. Since the bytes are reversed and the lowest byte is at location 0x1000, the 
  2015. byte pointer can read the value fine.  If the bytes were not reversed, then the 
  2016. value at 0x1000 would hold a zero and the byte pointer would receive the wrong 
  2017. value.  This is the rationale behind the reversed byte order scheme. 
  2018.  
  2019. For this same reason, the bytes that make up a ULONG are reversed twice. You 
  2020. can look at ULONGs like two USHORTs, but the USHORTs are reversed so that the 
  2021. lowest 8 bits of the ULONG are placed at the first memory location (0x1000). 
  2022.  
  2023. What all this means for palettes is this:  You access the bytes in a PCX one 
  2024. after another in the order of Red, Green, Blue. 
  2025.  
  2026. byRed = *(pbyColor + 0);
  2027. byGreen = *(pbyColor + 1);
  2028. byBlue = *(pbyColor + 2);
  2029.  
  2030. If accessed with a byte pointer, the bytes in an OS/2 palette are accessed in 
  2031. the order Blue, Green, Red, Flag. 
  2032.  
  2033. byBlue = *(pbyColor + 0);
  2034. byGreen = *(pbyColor + 1);
  2035. byRed = *(pbyColor + 2);
  2036. byFlag = *(pbyColor + 3);
  2037.  
  2038. For implementation of a PCX decoder and encoder, check out the sample source 
  2039. code that comes with this article.  Handling the header, codec, and palette can 
  2040. all be seen in pcx.cpp.  The handling of the byte reversal scheme can be seen 
  2041. in the Convert() routine of os2pal.cpp. 
  2042.  
  2043. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2044.  
  2045.  
  2046. ΓòÉΓòÉΓòÉ 7.7. The PcxPainter object ΓòÉΓòÉΓòÉ
  2047.  
  2048. The PcxPainter object 
  2049.  
  2050. The PcxPainter object is derived from the BitmapPainter object.  All of the 
  2051. member functions called by a program are virtual functions in the BitmapPainter 
  2052. object, so you could just as easily replace the PcxPainter object with a 
  2053. GifPainter or TifPainter, and not have to change much of anything else in your 
  2054. program.  The functions of the BitmapPainter object are: 
  2055.  
  2056. AssociateCanvas():  this routine tells the BitmapPainter object what canvas is 
  2057. to be used for the uncompressed graphic.  If the canvas is not large enough for 
  2058. the graphic, the information outside of the canvas will be discarded. 
  2059.  
  2060. DissociateCanvas():  this routine clears the internal pointers to the canvas. 
  2061.  
  2062. AssociateBuffer():  this routine is used to tell the object where the encoded 
  2063. graphic is in memory.  Such a buffer might be created by finding the size of a 
  2064. PCX file, allocating that much memory, and then reading the entire PCX file 
  2065. into that buffer.  In the PcxPainter object, the AssociateBuffer() routine also 
  2066. checks the buffer to see if it contains valid PCX information before it accepts 
  2067. the buffer.  If the buffer does not contain valid information or is of an 
  2068. unsupported PCX type (16 color), then the routine returns with an error. 
  2069.  
  2070. DissociateBuffer():  this clears the internal pointers to the buffer. 
  2071.  
  2072. PaintCanvas():  this instructs the object to take the compressed graphic 
  2073. specified in AssociateBuffer(), decompress it, and display it to the canvas 
  2074. specified with AssociateCanvas(). This routine also determines the palette of 
  2075. the graphic, and stores it in an internal buffer. 
  2076.  
  2077. EncodeCanvas():  For PcxPainter, EncodeCanvas() will take the entire canvas 
  2078. specified with AssociateCanvas(), encodes it in PCX format, and stores it in an 
  2079. internal buffer.  It allocates and uses an internal buffer because the size of 
  2080. the compressed graphic is not known when the routine is called.  EncodeCanvas() 
  2081. will return a pointer to the internal buffer, as well as the size of this 
  2082. buffer. 
  2083.  
  2084. FreeEncodeBuffer():  This causes the internal buffer that EncodeCanvas() 
  2085. allocated to be deallocated. 
  2086.  
  2087. QueryBitmapStats():  This routine looks at the information in the buffer 
  2088. specified by AssociateBuffer(), and fills in the provided structure with the 
  2089. bitmap width, height, and color depth. 
  2090.  
  2091. MonoSetWhite() and MonoSetBlack():  These routines set the color index to be 
  2092. used for the black or the white pixels when a monochrome bitmap is decoded. 
  2093. Since the target canvas is a 256 color canvas, values from 0 to 255 may be 
  2094. specified. 
  2095.  
  2096. QueryPaletteBuffer():  This routine returns a pointer to the internal buffer 
  2097. with the palette info.  The palette data is stored with three bytes per palette 
  2098. entry, and the bytes specify the red, green, and blue components of the color 
  2099. respectively. 
  2100.  
  2101. QueryLastErrorCode():  This returns a code for the last error encountered, and 
  2102. its value can be used to look up the error code from the resource file's string 
  2103. table.  The codes are specified in errcodes.hpp and the error strings are 
  2104. specified in game2.msg. 
  2105.  
  2106. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2107.  
  2108.  
  2109. ΓòÉΓòÉΓòÉ 7.8. Conclusion and News of the Future ΓòÉΓòÉΓòÉ
  2110.  
  2111. Conclusion and News of the Future 
  2112.  
  2113. Well, that's about it for my second article in Gearing Up For Games.  As 
  2114. always, comments, flames, and questions are welcomed.  I can be reached at the 
  2115. email address listed in the "Contributors" section. 
  2116.  
  2117. Next time I will probably look into threads, semaphores, timers and other 
  2118. multitasking concerns.  If I have time, I may start on how to draw sprites as 
  2119. well. 
  2120.  
  2121. In the future, I will be looking into the fullscreen support aspects of DIVE. 
  2122. I recently added fullscreen support to a project I'm working on, and it was a 
  2123. fairly simple process.  It took about 15 minutes to write all the code needed 
  2124. to implement fullscreen support, an hour to get the darn thing to compile 
  2125. (problems with parameter passing since header files for fullscreen support 
  2126. don't exist yet), and another hour working out undocumented pitfalls of 
  2127. fullscreen modes.  I'll be certain to give a full report in a couple of months 
  2128. as availability of the Games SDK draws closer. 
  2129.  
  2130. It looks like the Games SDK will be released through the DevCon CD subscription 
  2131. program.  For those of you unfamiliar with DevCon, it is subscription that 
  2132. comes four times a year, and each "issue" contains several CDs with 
  2133. information, toolkits, and sample code on them, as well as a paper newsletter 
  2134. with articles on various aspects of developing for OS/2.  I included ordering 
  2135. information in my last article, so I won't repeat it here. I don't know if the 
  2136. Games SDK will be released through other means other than DevCon.  I think that 
  2137. IBM should release it freely, but that is just my (and a lot of other people's) 
  2138. opinion. 
  2139.  
  2140. Also, I have recently learned that IBM has released joystick drivers for OS/2. 
  2141. The drivers can be obtained by anonymous ftp to ftp01.ny.us.ibm.net in the 
  2142. /pub/games directory.  The filename is JOYSTICK.ZIP.  I haven't found any 
  2143. programming information for these drivers yet, but I'll be sure to fill 
  2144. everyone in on what I can find as soon as I find it! 
  2145.  
  2146. Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2147.  
  2148.  
  2149. ΓòÉΓòÉΓòÉ 7.9. Whoops! ΓòÉΓòÉΓòÉ
  2150.  
  2151. Whoops! 
  2152.  
  2153. Well, looks like I made a few mistakes in the code for my last article. Time to 
  2154. come clean on them: 
  2155.  
  2156.    1. In game1.rc, the ICON statement should read: 
  2157.  
  2158.             ICON   ID_APPMAIN   game1.ico
  2159.  
  2160.    2. The file game1.msg was not needed.  GAME2 uses .MSG files however. 
  2161.  
  2162.    3. The Canvas::QueryWidth() and Canvas::QueryHeight() methods should return 
  2163.       USHORTs instead of SHORTs. 
  2164.  
  2165.    4. In the article itself, the colors were wrong for the picture of the 
  2166.       sample code's output.  This happened because I did not convert the 
  2167.       palette of the bitmap to the system palette before I submitted it. 
  2168.  
  2169.  Compiling the Sample Code With the Watcom Compiler 
  2170.  
  2171.  I did not give instructions on how to get the sample code to compile with the 
  2172.  Watcom compiler (which I actually use by the way.)  To use the DevCon toolkit 
  2173.  with Watcom, the following things must be done: 
  2174.  
  2175.  In Your C/CPP Compilations 
  2176.  
  2177.  First, for all of your C and CPP files that use the DevCon Warp Toolkit, add: 
  2178.  
  2179.   #define __IBMC__
  2180.  
  2181.  before you include any of the DevCon header files.  Note that there are two 
  2182.  underscores both before and after the "IBMC", not just one. 
  2183.  
  2184.  Also make sure that the compiler is looking in the \H directory of your DevCon 
  2185.  toolkit for header files, not in the WATCOM\H\OS2 directory. 
  2186.  
  2187.  In The File mmioos2.h 
  2188.  
  2189.  Find the section titled :  "Country codes (CC), languages (LC), and dialects 
  2190.  (DC)." 
  2191.  
  2192.  You will notice that some of the defines in this section begin with a zero. 
  2193.  This causes the Watcom compiler to read these numerals as octals (as any good 
  2194.  ANSI compiler would <grin>).  Remove these zeroes.  Therefore the definition: 
  2195.  
  2196.   #define MMIO_CC_USA                       001
  2197.  
  2198.  would become 
  2199.  
  2200.   #define MMIO_CC_USA                         1
  2201.  
  2202.  This needs to be done from MMIO_CC_NONE (value of 0) to MMIO_CC_TURKEY (value 
  2203.  of 90). 
  2204.  
  2205.  In Your Linker setup 
  2206.  
  2207.  Don't forget to include the library mmpm2.lib when you link. This can either 
  2208.  be done in the IDE in the menu "Options \ OS/2 Linking Switches \2.Import, 
  2209.  Export and Library Switches" in the "Libraries(,):[libr]" window, or in the 
  2210.  command line of your linker with the statement "libr mmpm2.lib" (without the 
  2211.  double quotes, of course). 
  2212.  
  2213.  Also, be certain to have a large enough stack for your program.  The default 
  2214.  stack for the Watcom IDE is about 8K I think.  The MMPM/2 documentation 
  2215.  suggests at least a 16Kb stack, but I compile with a 32K stack. 
  2216.  
  2217.  Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2218.  
  2219.  
  2220. ΓòÉΓòÉΓòÉ 8. Programming the WPS Using the UICL ΓòÉΓòÉΓòÉ
  2221.  
  2222.  
  2223. ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
  2224.  
  2225. Programming the WPS Using the UICL 
  2226.  
  2227. Written by Juergen Riedl 
  2228.  
  2229. Introduction 
  2230.  
  2231. About one year ago I posted a question onto the net asking whether or not it is 
  2232. possible to develop WPS classes with IBM's User Interface Class Libraries 
  2233. (UICL), but even IBM itself couldn't give me an answer, so I forgot about it. 
  2234. In April this year, however, I was offered by the OS/2 User Group of the 
  2235. Technical University of Munich (Bavaria / Germany) to give a review of the book 
  2236. about the UICL entitled OS/2 C++ Class Library, Power GUI Programming with C 
  2237. Set++ by Leong, Law, Love, Tsuji and Olson.  I remembered my wish a year ago, 
  2238. started my first simple steps to program the WPS using the UICL, stumbled into 
  2239. some mysterious probems.  But with some luck I got it to work ("1% inspiration 
  2240. but 99% transpiration", Thomas Edison). 
  2241.  
  2242. This submission is the attempt to share my experiences with you, in the hope to 
  2243. enable you to easily write applications which are completely integrated into 
  2244. the WPS using the UICL.  If this is to your taste then follow me on the journey 
  2245. to see that it is not too difficult. 
  2246.  
  2247. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2248.  
  2249.  
  2250. ΓòÉΓòÉΓòÉ 8.2. The Paradigms ΓòÉΓòÉΓòÉ
  2251.  
  2252. The Paradigms 
  2253.  
  2254. Frequently, IBM has created sophisticated APIs but never invested sufficient 
  2255. effort to publish the required documents to enable programmers to use them. 
  2256. This situation has slightly changed for the WPS [1, 2] and has been 
  2257. considerably improved for the UICL [3]. 
  2258.  
  2259. The WPS represents the paradigm which enables you to use your computer in an 
  2260. document-centered fashion.  But due to the lack of good guidance, developing 
  2261. WPS classes is a rather difficult task.  The PM API is abstracted from you; you 
  2262. don't see any function responsible for message processing; you don't even see 
  2263. an easy way to extent their functionality.  In my opinion this is the reason 
  2264. why 99% of all OS/2 applications follow the old PM style paradigm.  Any WPS 
  2265. programmer will be seen as a guru, which in fact they are. <grin> 
  2266.  
  2267. I made my first steps of WPS programming guided by the book Client/Server 
  2268. Programming with OS/2 2.1 by Orfaly and Harkey.  But I didn't like WPS 
  2269. programming very much - even small bugs in my classes required rebooting the 
  2270. machine.  So it was burdensome.  This changed dramatically with the advent of 
  2271. OS/2 3.0 Warp which designed the WPS as a DSOM server.  Instead of rebooting 
  2272. the machine as before, the WPS was usually the one restarted.  Along the way, I 
  2273. learned to like the UICL, which presented the obvious question:  why should I 
  2274. program in the old PM style after having tasted the sweet flavour of the UICL? 
  2275.  
  2276. At a first glance, the UICL appears to be a wrapper of PM.  If you take the 
  2277. time, though, you will realize that it is more:  it provides the means of 
  2278. creating sophisticated classes with few lines of code instead of hundreds as 
  2279. the pure PM programmer is forced to do.  Even though the UICL is that powerful 
  2280. it seems to me to contradict the aim of the WPS, which is to support the 
  2281. document-centered paradigm.  All of the "programs" should be seamlessly 
  2282. integrated into the shell, like extensions; no one should start any application 
  2283. first and generate the document afterwards as in the past.  But with the UICL 
  2284. the obvious way is to generate an EXE which will be attached to the usual 
  2285. program notebook of the WPS.  Wouldn't it be nice to be able to open a 
  2286. customized notebook of this application as any other WPS object? 
  2287.  
  2288. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2289.  
  2290.  
  2291. ΓòÉΓòÉΓòÉ 8.3. Mastering the First Step ΓòÉΓòÉΓòÉ
  2292.  
  2293. Mastering the First Step 
  2294.  
  2295. You have read the file README.1ST and set up your environment accordingly?  All 
  2296. right, lets start. 
  2297.  
  2298. What do we want to do?  We want to develop a WPS application comprising a 
  2299. notebook and a frame window.  Will this application be a "killer application?" 
  2300. No, it is only a sample to show how to implement the WPS and UICL combination. 
  2301. The development of the "killer application" is up to you.  But it will become 
  2302. far easier in my opinion. 
  2303.  
  2304. We will begin by subclassing WPAbstract.  WPAbstract provides two notebook 
  2305. pages, the Window page and the General page.  For the first step, we will 
  2306. extend this class to open an ordinary "Hello World" frame window by double 
  2307. clicking on its icon. After that we will examine how to add customized notebook 
  2308. pages to the already defined ones.  And, of course, all of this will be done 
  2309. using the UICL! 
  2310.  
  2311. Since we are dealing with the WPS we must use the SOM IDL.  (The new 
  2312. VisualAge++ compiler may change this with its Direct To SOM capability) But it 
  2313. is not difficult to follow the code; examine the file OS2UG.IDL (for 
  2314. information on SOM and WPS please read EDM/2 issues 2-8 and 2-9): 
  2315.  
  2316. interface XWPS : WPAbstract
  2317. {
  2318. #ifdef __SOMIDL__
  2319.   implementation {
  2320.  
  2321.     //# Class Modifiers
  2322.     majorversion = 1;
  2323.     minorversion = 2;
  2324.     dllname = "os2ug.dll";
  2325.     metaclass = M_XWPS;
  2326.     callstyle = oidl;
  2327.     passthru C_xih_before =
  2328. "#include <os2.h>";
  2329.  
  2330.     //# Method Modifiers
  2331.     wpModifyPopupMenu : override;
  2332.     wpMenuItemSelected: override;
  2333.     wpOpen            : override;
  2334.     wpAddSettingsPages: override;
  2335.  
  2336.   };
  2337. #endif // __SOMIDL__
  2338. };
  2339.  
  2340. As you might assume looking at the class declaration interface, XWPS : 
  2341. WPAbstract sounds like class XWPS : public WPAbstract in C++.  Outside of the 
  2342. implementation block, neither additional instance variables nor functions are 
  2343. declared.  For that reason, no release order section is required.  To be 
  2344. compliant with the WPS call style, set callstyle = oidl.  If you will write 
  2345. CORBA-compliant DSOM classes, you must set callstyle = corba.  But this doesn't 
  2346. apply to WPS GUI classes yet.  During this article, we will override some WPS 
  2347. instance methods, which begin with the letters wp.  For the first step, we will 
  2348. focus on three methods; the method wpAddSettingsPages() is the subject of the 
  2349. second step.  Each of them will be discussed separately. 
  2350.  
  2351. Now take a look onto the metaclass declaration interface M_XWPS: 
  2352.  
  2353. interface M_XWPS
  2354. // same as interface M_XWPS: M_WPAbstract
  2355. {
  2356. #ifdef __SOMIDL__
  2357.   implementation {
  2358.  
  2359.     //# Class Modifiers
  2360.     majorversion = 1;
  2361.     minorversion = 2;
  2362.     callstyle = oidl;
  2363.  
  2364.     //# Method Modifiers
  2365.     wpclsQueryStyle: override;
  2366.     wpclsQueryTitle: override;
  2367.     wpclsQueryDefaultView: override;
  2368.  
  2369.   };
  2370. #endif // __SOMIDL__
  2371. };
  2372.  
  2373. Here you see that SOM is slightly different from C++.  It provides different 
  2374. types of classes and subsequently different types of methods: class methods and 
  2375. instance methods.  Class methods are tied to metaclasses.  Metaclasses are 
  2376. responsible for the management of class resources, and they provide the "bed" 
  2377. for the instance of a class like you do with the constructor of a C++ class. 
  2378. For the first step we need to override three class methods, which begin with 
  2379. the letters wpcls.  Each of them will be discussed separately. 
  2380.  
  2381. After you have declared the interfaces in your IDL file, you will run the SOM 
  2382. compiler SC against it.  Enter SC OS2UG.IDL to compile the file.  The SOM 
  2383. compiler generates an XH, an XIH, a CPP and a DEF file.  Because it is common 
  2384. programming style to separate each function into a separate file, please do so 
  2385. accordingly.  Unfortunately, the SOM compiler not only generates declarations, 
  2386. but also definitions within its header files; later you have to write a source 
  2387. file which #include's all of the separate files. 
  2388.  
  2389. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2390.  
  2391.  
  2392. ΓòÉΓòÉΓòÉ 8.4. Overriding wpclsQueryStyle ΓòÉΓòÉΓòÉ
  2393.  
  2394. Overriding wpclsQueryStyle 
  2395.  
  2396. While developing WPS classes, you need to register and deregister them many 
  2397. times.  You can avoid this by disabling the generation of a template of your 
  2398. WPS class.  If you do not, you can only get rid of the template by rebooting 
  2399. into a command shell without the WPS running and delete the corresponding 
  2400. DLL's.  With an additional reboot you can continue development.  I disable the 
  2401. generation of a template to make life easier; this is achieved as follows (see 
  2402. the file m_qstyle.cpp): 
  2403.  
  2404. SOM_Scope ULONG  SOMLINK wpclsQueryStyle(M_XWPS *somSelf)
  2405. {
  2406.     /* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
  2407.     M_XWPSMethodDebug("M_XWPS","wpclsQueryStyle");
  2408.  
  2409.     return (M_XWPS_parent_M_WPAbstract_wpclsQueryStyle(somSelf)
  2410.             | CLSSTYLE_NEVERTEMPLATE); // no templates
  2411. } // END wpclsQueryStyle()
  2412.  
  2413. It returns the parents style or'd with the style CLSSTYLE_NEVERTEMPLATE. 
  2414. That's all you need.  The result is that now the template checkbox on the 
  2415. General page is not available. Thus you can deregister your class after 
  2416. deleting the instance and delete the DLL without the need to reboot your 
  2417. machine. 
  2418.  
  2419. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2420.  
  2421.  
  2422. ΓòÉΓòÉΓòÉ 8.5. Overriding wpclsQueryTitle ΓòÉΓòÉΓòÉ
  2423.  
  2424. Overriding wpclsQueryTitle 
  2425.  
  2426. If you like to have a default title of your new class you will set it here (see 
  2427. the file m_qtitle.cpp). 
  2428.  
  2429. SOM_Scope PSZ  SOMLINK wpclsQueryTitle(M_XWPS *somSelf)
  2430. {
  2431.     /* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
  2432.     M_XWPSMethodDebug("M_XWPS","wpclsQueryTitle");
  2433.  
  2434.     return (ClassTitle);
  2435. } // END wpclsQueryTitle()
  2436.  
  2437. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2438.  
  2439.  
  2440. ΓòÉΓòÉΓòÉ 8.6. Overriding wpclsQueryDefaultView ΓòÉΓòÉΓòÉ
  2441.  
  2442. Overriding wpclsQueryDefaultView 
  2443.  
  2444. When you double click on the icon, which view should be opened?  The settings 
  2445. notebook or the frame window?  Our sample class opens a frame window (see the 
  2446. file m_qdefvw.cpp).  This is done by declaring the value OPEN_XWPS1 (see the 
  2447. file os2ug.h) which is one of three possible frame windows: 
  2448.  
  2449. SOM_Scope ULONG  SOMLINK wpclsQueryDefaultView(M_XWPS *somSelf)
  2450. {
  2451.     /* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
  2452.     M_XWPSMethodDebug("M_XWPS","wpclsQueryDefaultView");
  2453.  
  2454.     return (OPEN_XWPS1);
  2455. }// END wpclsQueryDefaultView()
  2456.  
  2457. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2458.  
  2459.  
  2460. ΓòÉΓòÉΓòÉ 8.7. Overriding wpModifyPopupMenu ΓòÉΓòÉΓòÉ
  2461.  
  2462. Overriding wpModifyPopupMenu 
  2463.  
  2464. When you click with mouse button 2 (default right) on your application's icon, 
  2465. you would like to find a menu reflecting your default view.  This will be added 
  2466. to the overridden function above (see the file modpupmu.cpp): 
  2467.  
  2468. SOM_Scope BOOL  SOMLINK wpModifyPopupMenu(XWPS *somSelf,
  2469.                                           HWND hwndMenu,
  2470.                                           HWND hwndCnr,
  2471.                                           ULONG iPosition)
  2472. {
  2473.    zString    ModulePathName;             // DLL Module path and name
  2474.    HMODULE    hmod;                       // DLL MODULE handle
  2475.  
  2476.  
  2477.    /* XWPSData *somThis = XWPSGetData(somSelf); */
  2478.    XWPSMethodDebug("XWPS","wpModifyPopupMenu");
  2479.  
  2480.    // Get Module Name and Handle
  2481.    const IDynamicLinkLibrary dynid(cDllName); // dll name: OS2UG.DLL
  2482.  
  2483.    hmod = dynid.handle();
  2484.  
  2485.    // Insert "Hello OS2UG" into Open Menu
  2486.    if (!somSelf->wpInsertPopupMenuItems( hwndMenu, 0,
  2487.                                  hmod, ID_OPENMENU, WPMENUID_OPEN))    {
  2488.       DebugMsg("Error in wpModifyPopupMenu()",ModulePathName );
  2489.    }
  2490.    return (TRUE);
  2491. } // END wpModifyPopupMenu()
  2492.  
  2493. To retrieve the module handle of the DLL which contains the binaries for your 
  2494. popup menu I chose to use an instance of IDynamicLinkLibrary, a class of the 
  2495. UICL.  The usual approach would be to call the SOM function 
  2496. somLocateClassFile(), but this doesn't work on my machine (your mileage may 
  2497. vary): 
  2498.  
  2499. ModulePathName = (*SOMClassMgrObject)
  2500.                     .somLocateClassFile(                                     SOM_IdFromString(ClassTitle),
  2501.                                     XWPS_MajorVersion,
  2502.                                     XWPS_MinorVersion);
  2503. DosQueryModuleHandle( ModulePathName, &hmod);
  2504.  
  2505. It would be a nice exercise for you to try both methods.  <grin> 
  2506.  
  2507. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2508.  
  2509.  
  2510. ΓòÉΓòÉΓòÉ 8.8. Overriding wpMenuItemSelected ΓòÉΓòÉΓòÉ
  2511.  
  2512. Overriding wpMenuItemSelected 
  2513.  
  2514. Now you have decided to open the "Hello OS2UG" view and the WPS processes the 
  2515. overridden method wpMenuItemSelected() (see the file muimsel.cpp).  Here you 
  2516. will call wpViewObject() to open a view. This function calls your application's 
  2517. frame window routine: 
  2518.  
  2519. SOM_Scope BOOL  SOMLINK wpMenuItemSelected(XWPS *somSelf,
  2520.                                                 HWND hwndFrame,
  2521.                                                 ULONG ulMenuId)
  2522. {
  2523.     /* XWPSData *somThis = XWPSGetData(somSelf); */
  2524.     XWPSMethodDebug("XWPS","wpMenuItemSelected");
  2525.  
  2526.     switch( ulMenuId )
  2527.     {
  2528.        case OPEN_XWPS1:
  2529.           somSelf->wpViewObject( hwndFrame, OPEN_XWPS1, 0);
  2530.           break;
  2531.        case OPEN_XWPS2:
  2532.           somSelf->wpViewObject( hwndFrame, OPEN_XWPS2, 0);
  2533.           break;
  2534.        case OPEN_XWPS3:
  2535.           somSelf->wpViewObject( hwndFrame, OPEN_XWPS3, 0);
  2536.           break;
  2537.        default:
  2538.           return (XWPS_parent_WPAbstract_wpMenuItemSelected
  2539.                         (somSelf, hwndFrame, ulMenuId));
  2540.     }
  2541.     return TRUE;
  2542.  
  2543. } // END wpMenuItemSelected()
  2544.  
  2545. Have you discovered that you can open three different views OPEN_XWPS1, 
  2546. OPEN_XWPS2 and OPEN_XWPS3?  These start a frame window in either a separate 
  2547. thread, within the WPS thread of your notebook, or in a separate process, 
  2548. respectively. 
  2549.  
  2550. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2551.  
  2552.  
  2553. ΓòÉΓòÉΓòÉ 8.9. Overriding wpOpen ΓòÉΓòÉΓòÉ
  2554.  
  2555. Overriding wpOpen 
  2556.  
  2557. Here you see the transition from the WPS world to your application's world, the 
  2558. "Hello WPS" frame window (see the file open.cpp).  Here you call one of the 
  2559. CreateTUM_OS2_UGView*() methods, which are responsible for creating your frame 
  2560. window: 
  2561.  
  2562. SOM_Scope HWND  SOMLINK wpOpen(XWPS *somSelf, HWND hwndCnr,
  2563.                                     ULONG ulView, ULONG param)
  2564. {
  2565.    /* XWPSData *somThis = XWPSGetData(somSelf); */
  2566.    XWPSMethodDebug("XWPS","wpOpen");
  2567.  
  2568.    switch (ulView)
  2569.    {
  2570.      case OPEN_XWPS1:
  2571.            ptrIcon = somSelf->wpQueryIcon();
  2572.            return CreateTUM_OS2_UGViewA(somSelf);
  2573.            break;
  2574.      case OPEN_XWPS2:
  2575.            ptrIcon = somSelf->wpQueryIcon();
  2576.            return CreateTUM_OS2_UGViewB(somSelf);
  2577.            break;
  2578.      case OPEN_XWPS3:
  2579.            ptrIcon = somSelf->wpQueryIcon();
  2580.            return CreateTUM_OS2_UGViewC(somSelf);
  2581.            break;
  2582.  
  2583.    }   // end switch (ulView)
  2584.  
  2585.    return (XWPS_parent_WPAbstract_wpOpen
  2586.                 (somSelf, hwndCnr, ulView, param));
  2587.  } // END wpOpen()
  2588.  
  2589. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2590.  
  2591.  
  2592. ΓòÉΓòÉΓòÉ 8.10. Creating Your Frame Window ΓòÉΓòÉΓòÉ
  2593.  
  2594. Creating Your Frame Window 
  2595.  
  2596. If you're wondering why there hasn't been a lot of UICL usage, do not worry - 
  2597. to escape the WPS programming style a bit of work has to be done.  But this was 
  2598. only a few lines of code; now you can start to fly.  If you are ready to take 
  2599. off into the UICL heaven, let's begin. 
  2600.  
  2601. Within the function CreateTUM_OS2_UGViewB() you have the choice to create your 
  2602. frame window similar to the PM style (here in pseudo code, the actual code is 
  2603. in view_b.cpp): 
  2604.  
  2605. HWND CreateTUM_OS2_UGViewB(XWPS * somSelf){// view_b.cpp
  2606.  
  2607.         get the module handle;
  2608.         create the customized frame window;
  2609.         extract the frame window handle;
  2610.  
  2611. somSelf->wpRegisterView(frame window handle, frame window title);
  2612. return (frame window handle);
  2613. }// end CreateTUM_OS2_UGView()
  2614.  
  2615. Or you may create a separate thread for your application with the advantage of 
  2616. programming your application as usual in UICL.  First, you create an EXE file. 
  2617. After finishing, you rename the main() function to something else, which is 
  2618. called by the thread; finally, you change some lines of code as illustrated 
  2619. below (in pseudo code, the actual code is in view_a.cpp and threadm.cpp). 
  2620. Please compare threadm.cpp with main.cpp: 
  2621.  
  2622. HWND CreateTUM_OS2_UGViewA(XWPS * somSelf){// view_a.cpp
  2623.         set up a semaphore;
  2624.         IThread myThread(threadMain, semaphore adress);
  2625.  
  2626.         wait until semaphore is posted but no longer than x seconds;
  2627.         obtain frame window handle;
  2628.  
  2629. somSelf->wpRegisterView(frame window handle, frame window title );
  2630. return (frame window handle);
  2631. }// end CreateTUM_OS2_UGView()
  2632.  
  2633. void threadMain(void * arg) // threadm.cpp
  2634. {
  2635.         obtain the handle to the binary of the resource
  2636.         create customized frame window;
  2637.         extract the frame window handle;
  2638.         post frame window handle;
  2639.         IApplication::run();
  2640.  
  2641. }// end threadMain()
  2642.  
  2643. The third choice is to start your frame window as separate process.  Here you 
  2644. have to use named semaphores.  The pseudocode is identical with the threaded 
  2645. example with the exception that instead of a thread (see the file view_a.cpp) 
  2646. the process will be started by DosExecPgm() (see the files view_c.cpp and 
  2647. main.cpp).  Here is where the second part of the project comes into play. 
  2648.  
  2649. Look back at the discussion of the wpOpen() method:  you may create a frame 
  2650. window in another thread, the same thread, as well as in another process within 
  2651. the same sample application.  The best way to illustrate the differences is to 
  2652. start the clock with the second-hand enabled. I have programmed the frame 
  2653. window with the choice of "bigjob" being either multithreaded or running within 
  2654. the same thread.  Start "bigjob" and examine what happens with both the 
  2655. second-hand and the WPS when you try to select a different application! 
  2656.  
  2657. Now we will add some customized notebook pages to the WPS notebook.  The page 
  2658. contains a "Welcome" bitmap and an MLE instance.  [Note: the bitmap is a 
  2659. customized OS2LOGO.BMP, some of my friends got shocked seeing the "OS/2 Warp 2 
  2660. Alpha" during start-up of my machine.  It is only a joke; please do not send 
  2661. any email asking if I know any secrets about a new release of OS/2.] 
  2662.  
  2663. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2664.  
  2665.  
  2666. ΓòÉΓòÉΓòÉ 8.11. Overriding wpAddSettingsPages ΓòÉΓòÉΓòÉ
  2667.  
  2668. Overriding wpAddSettingsPages 
  2669.  
  2670. Here you see an excerpt of adsetpgs.cpp.  It is that simple to add additional 
  2671. pages to your WPS notebook.  Is it really that simple?  Yes, but you need a 
  2672. workaround for some strange behaviour which I noticed on my machine at least. 
  2673. If I would omit the IString instance the notebook would be reduced in size; 
  2674. thus none of the notebook pages are shown in entirety (see the note in the file 
  2675. adsetpgs.cpp). 
  2676.  
  2677. SOM_Scope BOOL  SOMLINK wpAddSettingsPages(XWPS *somSelf,
  2678.                                                 HWND hwndNotebook)
  2679. {
  2680.    /* XWPSData *somThis = XWPSGetData(somSelf); */
  2681.    XWPSMethodDebug("XWPS","wpAddSettingsPages");
  2682.  
  2683.    Boolean rc;
  2684.  
  2685.    IString
  2686.       s1("workaround for strange behaviour. Keep this string her!");
  2687.  
  2688.    // pages are added in reverse order, that is the last page first
  2689.  
  2690.    rc = somSelf->wpAddObjectGeneralPage(hwndNotebook);
  2691.    if (!rc) {
  2692.       DebugMsg("Error", "wpAddObjectGeneralPage()");
  2693.    } // endif
  2694.  
  2695.    addMLENotebookPage( hwndNotebook );
  2696.  
  2697.    rc = somSelf->wpAddObjectWindowPage(hwndNotebook);
  2698.    if (!rc) {
  2699.       DebugMsg("Error", "wpAddObjectWindowPage()");
  2700.    } // endif
  2701.  
  2702.    addFirstNotebookPage( hwndNotebook);
  2703.  
  2704.    return (rc);
  2705. } // END wpAddSettingsPages()
  2706.  
  2707. By principle any function to add to a UICL notebook page looks the same. Let's 
  2708. have a look on the pseudo code: 
  2709.  
  2710. void addAnyNotebookPage( HWND * notebook)
  2711. {
  2712.         prepare the notebook and the notebooks frame window handle;
  2713.  
  2714.         if a UICL frame window proxy doesn't exist create one;
  2715.         if a UICL notebook window proxy doesn't exist create one;
  2716.  
  2717.         prepare a notebook settings instance;
  2718.         add settings instance as first notebook page;
  2719.         attach a customized page settings handler to the notebook;
  2720. } // END  addAnyNotebookPage()
  2721.  
  2722. The customized page handler takes care that the page is initialized only once, 
  2723. when the page is first shown.  Only the page which will be shown will be 
  2724. instantiated.  Thus the opening of a notebook is much quicker than you creating 
  2725. all page instances at once.  I recommend this technique, because the user 
  2726. shouldn't be forced to wait too much. 
  2727.  
  2728. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2729.  
  2730.  
  2731. ΓòÉΓòÉΓòÉ 8.12. Conclusion ΓòÉΓòÉΓòÉ
  2732.  
  2733. Conclusion 
  2734.  
  2735. So my friend, you have followed me to the end of the journey.  I hope you will 
  2736. be able to create the killer application, fully integrated into the WPS with 
  2737. the help of the UICL.  The UICL improves the programming of OS/2 allowing you 
  2738. to develop applications quicker and with less effort. 
  2739.  
  2740. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2741.  
  2742.  
  2743. ΓòÉΓòÉΓòÉ 8.13. References ΓòÉΓòÉΓòÉ
  2744.  
  2745. References 
  2746.  
  2747. [1] Client/Server Programming with OS/2 2.1 by Robert Orfali and Dan Harkey, 
  2748. VNR / ISBN 0-442-01833-9 
  2749.  
  2750. [2] OS/2 Warp Workplace Shell API by Mindy Pollak, Wiley / ISBN 0-471-03872-5 
  2751.  
  2752. [3] OS/2 C++ Class Library Power GUI Programming with C-Set++ by Kevin Leong, 
  2753. William Law, Robert Love, Hiroshi Tsuji, and Bruce Olson, VNR ISBN 
  2754. 0-442-01795-2 
  2755.  
  2756. Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2757.  
  2758.  
  2759. ΓòÉΓòÉΓòÉ 9. 32-Bit I/O With Warp Speed ΓòÉΓòÉΓòÉ
  2760.  
  2761.  
  2762. ΓòÉΓòÉΓòÉ 9.1. Introduction ΓòÉΓòÉΓòÉ
  2763.  
  2764. 32-Bit I/O With Warp Speed 
  2765.  
  2766. Written by Holger Veit 
  2767.  
  2768. Introduction 
  2769.  
  2770. Well, I have a little bit of a bad feeling.  What I am going to describe in 
  2771. this article is something that should not be possible at the level of user 
  2772. application programs:  direct I/O.  This is the ability of a user program to 
  2773. talk to hardware resources directly, not controlled or even monitored by the 
  2774. operating system. 
  2775.  
  2776. Although it might have been common practice in a simple program loader like 
  2777. DOS, it is normally not a good idea in a modern multitasking or multi-user 
  2778. system.  In fact, OS/2, Windows NT, and the various UNIX derived operating 
  2779. systems, spend considerable efforts to hide this practice from user 
  2780. applications, or explicitly prohibit it. The reasons for that are obvious and 
  2781. well known: 
  2782.  
  2783.      User programs could access system resources, that means here hardware 
  2784.       devices, in an uncoordinated or uncooperative way, and could therefore 
  2785.       severely influence or even damage data integrity, system stability, and 
  2786.       security. 
  2787.  
  2788.      While the operating system tries to distribute the limited resources in a 
  2789.       fair way among the various competitors, a program that circumvents the 
  2790.       care of the operating system, could grab such a resource exclusively. 
  2791.       Even worse, it might struggle with the operating system for control, 
  2792.       which will unlikely have good consequences on the overall system 
  2793.       throughput. 
  2794.  
  2795.      Needless to say, a malign process like a computer virus could use a 
  2796.       feature like direct I/O to intentionally destroy data.  However, even 
  2797.       with good intention, a user program is not immune against software bugs 
  2798.       that might not only crash the program itself but also take the system 
  2799.       with it into the abyss. 
  2800.  
  2801.  On the other hand, people usually do not want to have I/O access to write 
  2802.  improved support for complicated disk or video devices.  Rather they have 
  2803.  simple I/O devices like data acquisition cards, parallel I/O boards, EPROM 
  2804.  programmer adapters or alike, that do not come with OS/2 support at all. 
  2805.  
  2806.  Writing a full-blown OS/2 device driver in order to reuse an old 8255 port 
  2807.  card seems like shooting sparrows with cannons.  In such a case, where neither 
  2808.  interrupt handling or DMA, nor physical access to adapter memory is involved, 
  2809.  direct I/O appears to be a feasible alternative.  In the following chapter, we 
  2810.  will look at the official methods that OS/2 offers to do I/O. 
  2811.  
  2812.  32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  2813.  
  2814.  
  2815. ΓòÉΓòÉΓòÉ 9.2. Doing Port I/O: The Front Doors ΓòÉΓòÉΓòÉ
  2816.  
  2817. Doing Port I/O: The Front Doors 
  2818.  
  2819. Device drivers 
  2820.  
  2821. No doubt, as was already stated, a device driver is the real solution. Keep 
  2822. critical tasks away from the user is the rule of the game.  The path to this is 
  2823. quite stony, however. 
  2824.  
  2825. As often criticized, device drivers in OS/2 are still 16 bit code.  This has 
  2826. several disadvantages. 
  2827.  
  2828.      You need to code entirely in assembler, or find a C compiler that still 
  2829.       produces 16 bit code.  Most of the standard drivers that come with OS/2 
  2830.       were built with either MASM 5.1 or MSC 6.0.  It is not only the problem 
  2831.       that IBM relies on products of a competitor here, but simply that these 
  2832.       products are no longer available in stores, and the successors no longer 
  2833.       support OS/2. Fortunately, the recent, widely available Watcom 10.0 
  2834.       compiler is usable for device driver development. 
  2835.  
  2836.      Coding in 16 bit throws the developer back into the stone age where he 
  2837.       has to fight against 64K segments, far and near calls, moving around 
  2838.       selectors and grouping segments in a certain order. 
  2839.  
  2840.  Nevertheless, one could think about writing a device driver that you can use 
  2841.  to read and write I/O ports by issuing special DosDevIOCtl instructions. 
  2842.  Surprisingly, this is an unnecessary enterprise!  Not many OS/2 users know 
  2843.  that every stock OS/2 system comes with a device driver that comes with such a 
  2844.  functionality:  TESTCFG.SYS. 
  2845.  
  2846.  Besides some other functions that are beyond the scope of this article, 
  2847.  TESTCFG.SYS  offers two ioctls, one for reading I/O ports and another one for 
  2848.  writing.  See table 1 for the description of the functions and the simple 
  2849.  program fragment in figure 1 for an example. 
  2850.  
  2851.   Device name      "TESTCFG$"
  2852.  
  2853.   Description      Read data from I/O port
  2854.   IOCTL Category    0x80
  2855.   IOCTL Function    0x41
  2856.  
  2857.   Parameter packet   struct {
  2858.                USHORT portaddr;
  2859.                USHORT size;
  2860.              } param
  2861.  
  2862.   Data packet      struct {
  2863.                ULONG dataread;
  2864.              } data;
  2865.  
  2866.   Remarks        size=1: read 8-bit
  2867.              size=2: read 16-bit
  2868.              size=3: read 32-bit
  2869.  
  2870.   Description      Write data to I/O port
  2871.   IOCTL Category    0x80
  2872.   IOCTL Function    0x42
  2873.  
  2874.   Parameter packet   struct {
  2875.                USHORT portaddr;
  2876.                USHORT size;
  2877.                ULONG datawrite;
  2878.              } param
  2879.  
  2880.   Data packet      none
  2881.  
  2882.   Remarks        size parameter same as for function 0x42 param packet in
  2883.              "Writing OS/2 2.1 Device Drivers in C" book is wrong!
  2884.  
  2885.  Table 1: Ioctl API of TESTCFG.SYS for doing direct I/O 
  2886.  
  2887.   /* direct I/O with TESTCFG.SYS */
  2888.  
  2889.   #define INCL_DOSFILEMGR
  2890.   #define INCL_DOSDEVIOCTL
  2891.   #include <os2.h>
  2892.  
  2893.   HFILE fd;
  2894.   ULONG action, len;
  2895.   APIRET rc;
  2896.   struct {
  2897.           USHORT port;
  2898.           USHORT size;
  2899.   } par;
  2900.   struct {
  2901.           ULONG data;
  2902.   } dta;
  2903.  
  2904.   rc = DosOpen("/dev/testcfg$",
  2905.           &fd, &action, 0,
  2906.           FILE_NORMAL, FILE_OPEN,
  2907.           OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
  2908.           (PEAOP2)NULL);
  2909.   /* check error code.... */
  2910.  
  2911.   par.port = 0x84;        /* use a mostly harmless port */
  2912.   par.size = 1;           /* read byte */
  2913.  
  2914.   rc = DosDevIOCtl(fd, 0x80, 0x41,
  2915.           (PULONG)&par, sizeof(par), &len,
  2916.           (PULONG)&dta, sizeof(dta), &len);
  2917.   /* check error code.... */
  2918.  
  2919.   printf("Data was 0x%lx\n", dta.data);
  2920.  
  2921.   rc = DosClose(fd);
  2922.   /* needless to say: check.... */
  2923.  
  2924.  Figure 1: Sample code to read a port through TESTCFG.SYS 
  2925.  
  2926.  There is one drawback, and we will hear this argument again real soon:  it is 
  2927.  slow.  Why? 
  2928.  
  2929.  Now see, we are calling this function from a 32 bit user program.  The 
  2930.  DosDevIOCtl() will enter the kernel through a call gate which is some kind of 
  2931.  a protected door.  The kernel will then first check the validity of the 
  2932.  parameter and data packets, identify the target driver to perform this 
  2933.  function, and then call the appropriate driver entry point.  Note the driver 
  2934.  is 16 bit code, so the kernel must convert the addresses of the parameter and 
  2935.  data packets from 0:32 bit user space addresses to 16:16 bit device driver 
  2936.  addresses.  Finally, the driver itself must decode the command and dispatch it 
  2937.  to its routines. 
  2938.  
  2939.  I once tried to trace such an ioctl call with the kernel debugger, and 
  2940.  eventually gave up counting after following some hundred instructions without 
  2941.  seeing any driver code.  Compare this with a single IN or OUT instruction. 
  2942.  That's bureaucracy! 
  2943.  
  2944.  IOPL Segments 
  2945.  
  2946.  The second method is actually a leftover from earlier OS/2 1.X versions, hence 
  2947.  it is a 16 bit technique as well. 
  2948.  
  2949.  Let me elaborate here a bit on the method used to prevent I/O access by user 
  2950.  programs.  The Intel 286 and later (386, 486, Pentium) processors can execute 
  2951.  code at four different privilege levels.  Because they are nested and usually 
  2952.  drawn as concentric circles, these levels are frequently referred to as 
  2953.  privilege rings (or protection rings).  Ring 0 is the level with the highest 
  2954.  privilege, and ring 3 has the lowest privilege (see figure 2). 
  2955.  
  2956.  Figure 2: The privilege rings and their use in OS/2 
  2957.  
  2958.  If a process wants to run with a higher privilege than the one it currently 
  2959.  has, it must go through a special gate; one might also compare a gate with a 
  2960.  tunnel or "wormhole".  There are several types of gates such as interrupt, 
  2961.  trap, or task gates.  The only interesting type for us is the call gate.  A 
  2962.  call gate allows a one-way transfer of execution from a segment with some 
  2963.  privilege to another one with same or higher privilege.  The other direction, 
  2964.  that is from a "trustworthy" high-privileged code segment to a less trusted 
  2965.  lower-privileged segment, is not possible.  See figure 2. Figure 3: Allowed 
  2966.  and forbidden transactions with call gates 
  2967.  
  2968.  Two bits in the processor status register (the IOPL field) determine the level 
  2969.  that is necessary to execute I/O CPU instructions.  Any code with less than 
  2970.  this privilege level will trigger an exception at the first attempt to execute 
  2971.  such an instruction.  Table 2 lists the affected instructions. Certain 
  2972.  instructions will even cause an exception if the process has the privilege to 
  2973.  I/O.  These instructions require ring 0 privilege.  Table 2 also lists these 
  2974.  instructions (386 processor). 
  2975.  
  2976.   ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2977.   ΓöéInstruction is protected and causes an  ΓöéAffected instructions                   Γöé
  2978.   Γöéexception...                            Γöé                                        Γöé
  2979.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2980.   Γöéif not in Ring 0                        ΓöéLIDT, LGDT, LMSW, CLTS, HLT MOV DR*, regΓöé
  2981.   Γöé                                        Γöé/ MOV reg, DR* MOV TR*, reg / MOV reg,  Γöé
  2982.   Γöé                                        ΓöéTR* MOV CR*, reg / MOV reg, CR*         Γöé
  2983.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2984.   Γöéif in Real Mode or in Virtual 8086 Mode ΓöéAll the above plus LTR, STR, LLDT, SLDT,Γöé
  2985.   Γöé                                        ΓöéLAR, LSL, VERR, VERW ARPL               Γöé
  2986.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2987.   Γöéif not at IOPL privilege level or higherΓöéAll ring 0 instructions plus OUT, INS,  Γöé
  2988.   Γöé(in Protected Mode)                     ΓöéOUTS, REP INS, REP OUTS STI, CLI        Γöé
  2989.   Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  2990.   Γöéif not at IOPL privilege level or higherΓöéAll ring 0 and Virtual 8086 Mode        Γöé
  2991.   Γöé(in Virtual 8086 Mode)                  Γöéinstructions plus INT n (Note 1) PUSHF, Γöé
  2992.   Γöé                                        ΓöéPOPF, STI, CLI, IRET (Note 2)           Γöé
  2993.   ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  2994.  
  2995.  Note 1:  INT 3 (opcode 0xcc) and INTO are not affected 
  2996.  
  2997.  Note 2:  I/O instructions are enabled or disabled by the I/O permission map in 
  2998.  the 386 task state segment 
  2999.  
  3000.  Table 2: Privileged Instructions 
  3001.  
  3002.  In OS/2, the required privilege level for I/O is ring 2 or better, and tough 
  3003.  luck, any user process only runs in ring 3 (figure 2). 
  3004.  
  3005.  In order to get a controlled way to do I/O, the OS/2 developers provided a 
  3006.  method to execute 16 bit code at ring 2 level.  When the linker produces an 
  3007.  executable from several object files, it accepts a special attribute for code 
  3008.  segments under certain circumstances.  This attribute is named IOPL and is 
  3009.  specified in the segment declaration section of a linker definition file 
  3010.  (Consult appropriate linker documentation).  The linker then annotates the 
  3011.  code in a way that every call of a routine in this IOPL segment will be 
  3012.  directed through a call gate, rather than a simple call.  When such a program 
  3013.  is loaded into memory for execution, the loader code in the kernel will 
  3014.  generate a R3->R2 call gate for each target called in an IOPL segment (see 
  3015.  call gate X in figure 3). 
  3016.  
  3017.  Each time such a call gate is entered, the processor will gain ring 2 
  3018.  privilege and lose it again when leaving by a normal return instruction. 
  3019.  
  3020.  Apparently, this looked like a feature which could be abused, so the IBM 
  3021.  developers restricted it in a way that only segments in a DLL can get the IOPL 
  3022.  attribute.  This appears to be a built-in feature of the program loader, not 
  3023.  just the linker, as patching the appropriate tables in the executable will not 
  3024.  work. 
  3025.  
  3026.  This restriction is not a bad idea, as it is now no longer possible to make an 
  3027.  executable disguising as a normal program, but doing I/O inside.  There must 
  3028.  be an accompanying DLL, to arouse suspicion - or at least should do so. 
  3029.  
  3030.  This could have been an almost ideal way for moderate I/O - if IBM had 
  3031.  provided a similar method for 32 bit applications as well.  There is no 
  3032.  restriction in the processor itself concerning 32 bit I/O, as one might 
  3033.  suspect; it is an intentional limitation.  Since IBM will not support 16 bit 
  3034.  software any longer in OS/2 for the PowerPC, those unsecure interfaces will 
  3035.  disappear in the future. 
  3036.  
  3037.  Nevertheless, you can call routines in such a 16 bit IOPL DLL from a 32 bit 
  3038.  executable, and there are several example files floating around in various FTP 
  3039.  archives.  The key item here is thunking.  The main problem with calling code 
  3040.  of another size gender is that the program counter as well as the stack 
  3041.  pointer needs to be adjusted to the corresponding other size.  If address 
  3042.  parameters are passed through the stack, these addresses need to be converted 
  3043.  as well.  This is what a thunking routine does. 
  3044.  
  3045.  Usually the compiler generates such routines automatically when a 16 bit 
  3046.  routine is declared, and this is why many high- level programmers do not 
  3047.  encounter them at all.  However, even if they seem to be invisible, they 
  3048.  nevertheless contribute a considerable share to performance degradation if an 
  3049.  I/O routine in the IOPL DLL is called from a 32 bit application. 
  3050.  
  3051.  32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3052.  
  3053.  
  3054. ΓòÉΓòÉΓòÉ 9.3. Doing I/O: Searching for Mouse Holes ΓòÉΓòÉΓòÉ
  3055.  
  3056. Doing I/O: Searching for Mouse Holes 
  3057.  
  3058. In the last section, we have seen that it is possible to do direct I/O with the 
  3059. already available facilities.  The difficulty is just the excessive overhead 
  3060. that makes their use quite unattractive, and with the text of the preface still 
  3061. in mind, there can be no doubt that this is not incidental. 
  3062.  
  3063. However, as some of you might know about my ambitious pet project, it was 
  3064. indispensable for me to find an extremely fast alternative to the above stuff. 
  3065. Although I prefer writing a device driver for that kind of applications, it 
  3066. seemed entirely impossible to put a complete Xserver into a 16 bit device 
  3067. driver (that beast, with PEX, is as large as 2 MB - 32 bit code!).  Moving only 
  3068. the critical parts into a driver might work; unfortunately the XFree86 people 
  3069. are too creative for me, so it would be expectable that I'd be hurrying to get 
  3070. their recent changes integrated for the rest of my life. 
  3071.  
  3072. So let us discuss possible alternatives. 
  3073.  
  3074. Outwitting the Program Loader? 
  3075.  
  3076. As we have seen in the discussion of the IOPL mechanism, the bottleneck is the 
  3077. thunking code.  Interestingly, there exist types of call gates that can mediate 
  3078. among 32 and 16 bit code and do the necessary conversion of the program counter 
  3079. and stack pointer automatically.  Unfortunately, the program loader refuses to 
  3080. make them for us.  Likewise, there seems to be no chance to have it create a 
  3081. 32->32 bit call gate.  A brute force approach could be trying to identify the 
  3082. call gates it made for us and redirect them to the routines that we want to run 
  3083. with privilege.  Since we need certain instructions to manipulate the GDT or 
  3084. LDT (more on that later), this is not possible from a user program, because the 
  3085. kernel protects these structures well in a ring 0 segment.  Similar to the 
  3086. restriction not to pass a call gate in the wrong direction, a process cannot 
  3087. read, let alone write, data of a higher ring level.  This is not a real 
  3088. problem, if we have an accomplice with sufficient rights to do the dirty work 
  3089. for us:  a device driver. 
  3090.  
  3091. However, besides being a bad hack, such a solution is still half-hearted. Once 
  3092. we find a method to manipulate call gates, we no longer need to have this code 
  3093. separated in a DLL, as with the IOPL anachronism, but we could keep it in the 
  3094. executable itself.  Furthermore, while we are on this way, couldn't we just 
  3095. manipulate the code segment of the user process into a ring 0 one?  Let us 
  3096. think about this possibility. 
  3097.  
  3098. User Processes at Ring 0? 
  3099.  
  3100. During reading, you might have thought about the question how the processor 
  3101. knows which privilege the currently executed code has, and where it keeps this 
  3102. information.  This is pretty simple in protected mode:  somewhere in memory 
  3103. there are two tables that describe the location, size and properties of each 
  3104. memory segment.  They are called global descriptor table (GDT) and local 
  3105. descriptor table (LDT).  While the GDT describes system wide structures, there 
  3106. is usually an LDT for each process in the system.  Two special registers of the 
  3107. CPU, GDTR and LDTR, point to the beginning of the tables.  Each table is an 
  3108. array with elements of eight bytes in size.  The index into these arrays is 
  3109. fairly simple:  it is formed from the upper 13 bits of the 16 bit segment 
  3110. registers (CS, DS, ES, SS, FS, GS).  Bit 2 of these registers distinguishes 
  3111. between LDT and GDT, and the two lowest bits describe the current privilege the 
  3112. CPU is running.  What is most important is that any segment descriptor in the 
  3113. tables also contains two bits that determine the privilege level the code runs 
  3114. under. 
  3115.  
  3116. So the way to go seems clear:  get the content of the CS register, find the 
  3117. corresponding GDT or LDT entry, and switch the privilege bits to ring 0. This 
  3118. is possible.  However, this game will likely end very fast with a trap and the 
  3119. register display on the text mode screen.  Why? 
  3120.  
  3121. We have seen in figure 3 that privileged ring 0 code will never execute less 
  3122. privileged code.  However, certain system or application DLLs required by the 
  3123. user program still have ring 3 level.  So the unfortunate consequence is:  if 
  3124. your user program has privileges, it will lose the ability to call several 
  3125. system functions.  The immediately upcoming flash of an idea of promoting the 
  3126. system and user DLLs to the same level as well, is hopefully not meant 
  3127. seriously, as it will end up with all software running privileged. 
  3128.  
  3129. It therefore appears that any trick to raise the privilege of the user process 
  3130. introduces more problems rather than solving them.  Let us try to approach the 
  3131. problem from a totally different side.  Maybe we could reduce the overhead of 
  3132. performing functions in a device driver. A Back Door into a Driver: 
  3133. DevHlp_DynamicAPI 
  3134.  
  3135. Time to dive a bit deeper into a device driver.  The kernel provides a set of 
  3136. routines known as device helper functions to a device driver.  One of these 
  3137. helpers appears particularly attractive, as it promises to create a ring 0 gate 
  3138. directly into a device driver.  So the idea is to build the I/O functions into 
  3139. the driver and create such a dynamic API entry point.  This will return a GDT 
  3140. selector that a user process can enter with an indirect intersegment call 
  3141. instruction.  Estimating the overhead, this should be considerably faster than 
  3142. the bureaucratic way of TESTCFG.SYS. 
  3143.  
  3144. At least that's how it works in theory. 
  3145.  
  3146. In fact, I programmed it this way, and it worked, but it did not even reach the 
  3147. slow speed of TESTCFG.SYS.  Careful single stepping showed the following:  the 
  3148. DevHlp_DynamicAPI  created the call gate, but the gate did not point straight 
  3149. to the driver routine I wrote for the I/O access.  Instead, it pointed to 
  3150. somewhere in the kernel, into a routine DYNAM_API_4.  This entry point then 
  3151. performed almost all the fiddling I observed earlier when tracing the ioctl of 
  3152. TESTCFG.SYS. What was even worse was what the "4" in the label of the first 
  3153. routine told me.  I had broached a scarce resource.  Analysis showed that there 
  3154. are only 16 of these entry points available system wide, and mine was already 
  3155. the fifth one in use.  I have not the slight idea about the other four clients, 
  3156. but it does not seem to be a good idea to deliberately use up one of those 
  3157. expensive and rare interfaces. 
  3158.  
  3159. But in principle, the idea was correct. 
  3160.  
  3161. 32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3162.  
  3163.  
  3164. ΓòÉΓòÉΓòÉ 9.4. /DEV/FASTIO$ - the Final Way ΓòÉΓòÉΓòÉ
  3165.  
  3166. /DEV/FASTIO$ - the Final Way 
  3167.  
  3168. Okay.  We just managed to get a transforming (32->16bit) call gate, that just 
  3169. happens to point to the wrong address.  It was a matter of seconds to find the 
  3170. address of the corresponding GDT entry, and redirect it to the expected 
  3171. position.  A kernel debugger is really a neat tool for the hacker. It worked! 
  3172.  
  3173. At this point, calling the DevHlp_DynamicAPI function becomes useless, and will 
  3174. just occupy a later unusable entry point in the kernel.  A quick look into the 
  3175. list of device helper functions offers the function DevHlp_AllocGDTSelector. 
  3176. We acquire a default GDT selector for exclusive use by the driver, and "adjust" 
  3177. it to form a 32->16 bit R3->R0 call gate into the I/O routine section of the 
  3178. driver. 
  3179.  
  3180. Have a look at the code fragment in the FASTIO$ driver (figure 4) which does it 
  3181. all. 
  3182.  
  3183.                 .386p
  3184. _acquire_gdt    proc    far
  3185.         pusha
  3186.  
  3187.         mov     ax, word ptr [_io_gdt32]        ; get selector
  3188.         or      ax,ax
  3189.         jnz     aexit                           ; if we didn't have one
  3190.                                                 ; make one
  3191.  
  3192.         xor     ax, ax
  3193.         mov     word ptr [_io_gdt32], ax        ; clear gdt save
  3194.         mov     word ptr [gdthelper], ax        ; helper
  3195.  
  3196.         push    ds
  3197.         pop     es                              ; ES:DI = addr of
  3198.         mov     di, offset _io_gdt32            ; _io_gdt32
  3199.         mov     cx, 2                           ; two selectors
  3200.         mov     dl, DevHlp_AllocGDTSelector     ; get GDT selectors
  3201.         call    [_Device_Help]
  3202.         jc      aexit                           ; exit if failed
  3203.  
  3204.         sgdt    qword ptr [gdtsave]             ; access the GDT ptr
  3205.         mov     ebx, dword ptr [gdtsave+2]      ; get lin addr of GDT
  3206.         movzx   eax, word ptr [_io_gdt32]       ; build offset into table
  3207.         and     eax, 0fffffff8h                 ; mask away DPL
  3208.         add     ebx, eax                        ; build address in EBX
  3209.  
  3210.         mov     ax, word ptr [gdthelper]        ; selector to map GDT at
  3211.         mov     ecx, 08h                        ; a single entry (8 bytes)
  3212.         mov     dl, DevHlp_LinToGDTSelector
  3213.         call    [_Device_Help]
  3214.         jc      aexit0                          ; if failed exit
  3215.  
  3216.         mov     ax, word ptr [gdthelper]
  3217.         mov     es, ax                          ; build address to GDT
  3218.         xor     bx, bx
  3219.  
  3220.         mov     word ptr es:[bx], offset _io_call ; fix address off
  3221.         mov     word ptr es:[bx+2], cs          ; fix address sel
  3222.         mov     word ptr es:[bx+4], 0ec00h      ; a r0 386 call gate
  3223.         mov     word ptr es:[bx+6], 0000h       ; high offset
  3224.  
  3225.         mov     dl, DevHlp_FreeGDTSelector      ; free gdthelper
  3226.         call    [_Device_Help]
  3227.         jnc     short aexit
  3228.  
  3229. aexit0: xor     ax,ax                           ; clear selector
  3230.         mov     word ptr [_io_gdt32], ax
  3231. aexit:  popa                                    ; restore all registers
  3232.         mov     ax, word ptr [_io_gdt32]
  3233.         ret
  3234. _acquire_gdt    endp
  3235.  
  3236. Figure 4: Initialization routine of FASTIO$ driver 
  3237.  
  3238. Since a device driver is initialized in ring 3, this routine does not work 
  3239. during startup.  Rather, the driver will call this code once the first time 
  3240. some client opens the device.  Thus, to use the driver, a small routine 
  3241. io_init() needs to be called first.  Refer to the file iolib.asm that comes 
  3242. with this issue of EDM/2. 
  3243.  
  3244. A final improvement:  Usually, C code passes arguments on the stack. A call 
  3245. gate can be configured to copy these parameters over to the new ring. But why 
  3246. should we do this?  For really fast I/O access we pass the data in registers. 
  3247. This allows for direct replacement of I/O instructions in assembler code by a 
  3248. simple indirect call as shown in figure 5. The address of the indirect call is 
  3249. set up by the above mentioned io_init() procedure. 
  3250.  
  3251. EXTRN   ioentry:FWORD
  3252.   :
  3253. MOV     DX, portaddr
  3254. MOV     AL, 123
  3255. MOV     BX, 4           ; function code 4 = write byte
  3256. CALL    FWORD PTR [ioentry]
  3257.   :
  3258.  
  3259. Figure 5: Calling I/O from assembler 
  3260.  
  3261. If the code needs to be called from C, we simply write a small stub that wraps 
  3262. a stack frame envelope around it, just as shown in figure 6. 
  3263.  
  3264. ; Calling convention:
  3265. ;       void c_outb(short port,char data)
  3266. ;
  3267. ;
  3268.         PUBLIC  _c_outb
  3269.         PUBLIC  c_outb
  3270. _c_outb PROC
  3271. c_outb:
  3272.         PUSH    EBP
  3273.         MOV     EBP, ESP                ; set standard stack frame
  3274.         PUSH    EBX                     ; save register
  3275.         MOV     DX, WORD PTR [EBP+8]    ; get port
  3276.         MOV     AL, BYTE PTR [EBP+12]   ; get data
  3277.         MOV     BX, 4                   ; function code 4 = write byte
  3278.         CALL    FWORD PTR [ioentry]     ; call intersegment indirect 16:32
  3279.         POP     EBX                     ; restore bx
  3280.         POP     EBP                     ; return
  3281.         RET
  3282.         ALIGN   4
  3283. _c_outb ENDP
  3284.  
  3285. Figure 6: A C callable I/O function 
  3286.  
  3287. The file iolib.asm  contains a set of functions c_inX() and c_outX() for using 
  3288. I/O from any 32 bit compiler that supports the standard stack frame.  The files 
  3289. iolib.a and iolib.lib are precompiled versions; the file iolib.h contains the C 
  3290. prototypes. 
  3291.  
  3292. In the complete driver, I gave up a small amount of the theoretically reachable 
  3293. performance.  There are six basic I/O operations: IN and OUT instructions exist 
  3294. for transferring bytes, 16 bit words and 32 bit long words.  To become really 
  3295. fast, one would have to provide a separate GDT selector for each of them.  In a 
  3296. typical OS/2 system, this should not be a problem.  However, if now everyone 
  3297. would start to add more routines, each with its own entry point, this resource 
  3298. could become rather quickly a scarce one.  So I spent a function code, to be 
  3299. passed in the BX register, to multiplex the six functions into a single GDT 
  3300. selector.  Refer to the io_call entry point in the fastio_a.asm driver source 
  3301. file. 
  3302.  
  3303. 32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3304.  
  3305.  
  3306. ΓòÉΓòÉΓòÉ 9.5. Conclusion ΓòÉΓòÉΓòÉ
  3307.  
  3308. Conclusion 
  3309.  
  3310. The article demonstrated how a specialized device driver was used to assist a 
  3311. user process in performing direct I/O.  The final overhead, compared to a pure 
  3312. device driver or a DOS program implementation, is just the CPU cycles of the 
  3313. indirect intersegment call through the call gate and the return instruction. 
  3314. Every other available method significantly adds a performance penalty.  This 
  3315. also holds for I/O in a DOS Box, which was not explained in this article.  It 
  3316. is to be expected, however, that this method will not be available any longer 
  3317. in future Power PC systems, so avoid the demonstrated trick unless absolutely 
  3318. necessary. 
  3319.  
  3320. 32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3321.  
  3322.  
  3323. ΓòÉΓòÉΓòÉ 10. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
  3324.  
  3325.  
  3326. ΓòÉΓòÉΓòÉ 10.1. Introduction ΓòÉΓòÉΓòÉ
  3327.  
  3328. /dev/EDM2/BookReview 
  3329.  
  3330. Written by Carsten Whimster 
  3331.  
  3332. Introduction 
  3333.  
  3334. In /dev/EDM2/BookReview, I focus on development books and materials.  The 
  3335. column is written from the point of view of an intermediate PM C programmer and 
  3336. intermediate REXX programmer.  Pick up whichever book strikes your fancy, and 
  3337. join the growing group of people following our PM programming columns.  I have 
  3338. already reviewed a number of beginner's books, and will try to concentrate a 
  3339. bit more on intermediate techniques and special topics from now on. 
  3340.  
  3341. Please send me your comments and thoughts so that I can make this column as 
  3342. good as possible.  I read and respond to all mail. 
  3343.  
  3344. Programming the OS/2 Warp GPI is the most up-to-date book specifically covering 
  3345. the GPI, which I have reviewed yet. 
  3346.  
  3347. /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3348.  
  3349.  
  3350. ΓòÉΓòÉΓòÉ 10.2. Errata ΓòÉΓòÉΓòÉ
  3351.  
  3352. Errata 
  3353.  
  3354. My web page is finally coming of age, despite a minor accident.  The OS/2 
  3355. section has grown dramatically, and now has a large number of useful links to 
  3356. other OS/2 sites.  Check it out at 
  3357. http://www.undergrad.math.uwaterloo.ca/~bcrwhims/. 
  3358.  
  3359. My machine has been upgraded to an AMD DX4-100 with 20 Mb RAM and an ATI Mach64 
  3360. with 2 Mb DRAM.  Due to the increased speed and responsiveness, my interest in 
  3361. developing is growing once again.  I am working on an update to my POV-Panel/2, 
  3362. and also on a couple of other projects, including a POV-Ray editor, and a PM 
  3363. version of an old video game called Qix. We'll see how far I get with all of it 
  3364. though <grin>. 
  3365.  
  3366. /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3367.  
  3368.  
  3369. ΓòÉΓòÉΓòÉ 10.3. Programming the OS/2 Warp GPI ΓòÉΓòÉΓòÉ
  3370.  
  3371. Programming the OS/2 Warp GPI 
  3372.  
  3373. For a while now, the OS/2 world has been without an in-depth, up-to-date book 
  3374. on the GPI.  Now things are about to change, both because of this book, and 
  3375. also because Graham Winn's book has been updated as well.  Here are the chapter 
  3376. headings for this, the newest of Stephen Knight's and Jeffrey Ryan's OS/2 
  3377. books: 
  3378.  
  3379.      Overview 
  3380.      OS/2 Architecture 
  3381.      Graphic Primitives 
  3382.      Fonts 
  3383.      Building Blocks of the GPI 
  3384.      Transformations 
  3385.      Paths, Regions, Clipping, Boundary Accumulation, and Correlation 
  3386.      Printing Graphics 
  3387.      OS/2 Metafiles 
  3388.  
  3389.       Appendix A:  GPI Functions 
  3390.       Appendix B:  Working with the Diskette 
  3391.  
  3392.  This is a book by the author of Learning to Program OS/2 2.0 Presentation 
  3393.  Manager by Example, and it shows.  I criticized that particular book for only 
  3394.  including a single, monolithic program as the example the whole book was built 
  3395.  around.  This book has the same basic structure, but I won't reiterate my 
  3396.  criticism unless I feel that this book also suffers from the same faults that 
  3397.  I described in the first one. 
  3398.  
  3399.  Reading this book quickly showed that the authors' ability to explain 
  3400.  difficult material has not decreased with time.  The writing is lucid, and 
  3401.  more in-depth than the first book.  This book is quite unusual in that it 
  3402.  presents a complete, well-featured program in good detail throughout the 
  3403.  chapters.  The Overview presents the graphics application from the user's 
  3404.  perspective, and really is a user manual, albeit a little short. 
  3405.  
  3406.  The next chapter, inexplicably called OS/2 Architecture, spends most of its 
  3407.  time explaining the architecture of the GPI, and the OS/2 graphics viewing 
  3408.  pipeline.  The GPI architecture is quite complicated, and not really intuitive 
  3409.  at all, but when you spend some time reading up on it, a lot of it come 
  3410.  together.  I still wonder if there isn't a better way to do things, though. It 
  3411.  really does seem needlessly complicated to me.  Hopefully DIVE will give those 
  3412.  of us who prefer building things more manually a much-needed reprieve from the 
  3413.  GPI.  Anyway, enough complaining about the GPI! 
  3414.  
  3415.  The third chapter discusses graphic primitives like lines, circles, ovals, 
  3416.  rectangles, as well as graphic attributes like line width, line colour, 
  3417.  character colour, character shear, image colour, marker mix, and so on ad 
  3418.  infinitum.  There really are an absolutely astounding number of attributes to 
  3419.  worry about, but they can be grouped into logical subsets, of course.  These 
  3420.  subsets are then explained briefly, followed by explanations of the line and 
  3421.  arc primitives, including line join options.  Some of the specific line 
  3422.  options are outlined, but the main philosophy of the book is to explain only 
  3423.  the most common functions in detail.  Others may or may not get mentioned, but 
  3424.  you can rest assured that 90-95% of what you will use is here.  Some of the 
  3425.  fills are also explained here, including the functions that use them.  Also in 
  3426.  this chapter is an introduction to text primitives, or in other words, using 
  3427.  fonts in graphics.  Finally, we are treated to an introduction to bitmap 
  3428.  usage. 
  3429.  
  3430.  Chapter four is the first non-introductory chapter on any subject so far, and 
  3431.  it attacks fonts.  By the way, if you look at the chapter headings of this 
  3432.  book, and compare them to the chapter headings of Winn's book, you will see a 
  3433.  remarkable similarity there.  I suppose it is unavoidable to a certain extent, 
  3434.  but it doesn't look like a complete coincidence.  Indeed, Graham Winn is given 
  3435.  credit in the Acknowledgements section, so it looks like there is a fairly 
  3436.  close relationship between the various graphics-book authors working at IBM. 
  3437.  It should be interesting to see what Winn's new book will look like.  In any 
  3438.  case, back to the Fonts chapter.  This chapter, like the rest, has an 
  3439.  introductory paragraph giving a little background to the subject.  I prefer to 
  3440.  see a little more, and to have it also give a quick preview of what the 
  3441.  chapter contains so that you know where you are headed, but that could be just 
  3442.  personal preference.  After the introductory paragraph, we are told a bit 
  3443.  about codepages.  This is interesting material, but at the same time, I really 
  3444.  wish it didn't have to be there, ie.  IBM should take some initiative with 
  3445.  OS/2, and move towards double-byte characters, so that we won't have to deal 
  3446.  with codepages any more.  Yes, this would slow down our systems a bit, but I 
  3447.  think that in the long run, it is worth it.  But, back to our book.  Outline 
  3448.  fonts, image (bitmapped) fonts, kerning, font metrics, font attributes, and 
  3449.  width tables are all introduced, and explained, and some larger code snippets 
  3450.  out of the sample application are given. 
  3451.  
  3452.  The fifth chapter launches into an explanation of the building blocks that the 
  3453.  GPI is constructed from, such as graphics orders and elements.  Segments are 
  3454.  covered in good depth, and then the graphics viewer is introduced into our 
  3455.  subject matter.  Quite a bit of code is given along the way, in large-ish 
  3456.  chunks.  Sometimes it is a little hard to grasp everything, with so much 
  3457.  listed at a time. 
  3458.  
  3459.  The next chapter deals with the various transformations that the GPI allows 
  3460.  you to perform on objects, including revisiting the coordinate spaces.  You 
  3461.  generally draw your objects first, and then put them through the 
  3462.  transformations on the way to their final form.  A fair amount of matrix math 
  3463.  is needed to do this, so be sure that you are up on this subject before 
  3464.  attempting to read this chapter.  Of course, the GPI does supply the tools to 
  3465.  do this, but comprehension is important. 
  3466.  
  3467.  Paths, regions, and so on is chapter seven's subject.  It deals with the 
  3468.  possibility of creating paths and regions, and then using these to either 
  3469.  clip, fill, or otherwise modify various (other) objects.  This is a fairly 
  3470.  powerful technique, which you will most likely find a need for if you get into 
  3471.  GPI in any depth at all.  There are various ways to define paths and regions, 
  3472.  and ways of combining them.  Redrawing using regions is also explained.  Model 
  3473.  space clipping, page space clipping, device space clipping, and other clipping 
  3474.  related options are all sub-sections of this chapter.  In addition to these, 
  3475.  there is a section called correlation, which is a bit of a god-send to anyone 
  3476.  trying to design something like a Doom editor.  This subject deals with the 
  3477.  GPI's ability to select objects based on mouse- clicks and keystrokes.  To 
  3478.  this end, tags are explained here.  They are used with objects to yield the 
  3479.  desired granularity for the selection operation.  A medium-sized code snippet 
  3480.  goes along with this, but my feeling is that some more depth would have been 
  3481.  nice here. 
  3482.  
  3483.  Printing graphics is the next chapter, and it explains the device independence 
  3484.  of OS/2's printing sub-system, as well as a basic outline of the 
  3485.  graphics-printing relationship in OS/2.  Chapter 9 delves into OS/2's 
  3486.  metafiles, and the raison-d'etre for this otherwise fairly unused format. 
  3487.  Basically, it is meant as a go-along to the GPI, and is supposed to be used 
  3488.  for picture interchange between applications of different nature.  It saves 
  3489.  more information than the other non-native format of the drawing editor, TIFF, 
  3490.  in that drawing commands themselves can be stored in a metafile.  It is in 
  3491.  some ways more similar to a printer or the screen, than to other graphics 
  3492.  formats, in that it is handled as a device under OS/2.  Again, a large- ish 
  3493.  chunk of code is regurgitated at the end of the chapter, making the reading a 
  3494.  little heavier than usual.  With these large code-snippets, it is harder to 
  3495.  dissect what is necessary, and what is frills.  Still, a good deal more can 
  3496.  potentially be taught as opposed to small programs that do little. 
  3497.  
  3498.  The appendices have information on the GPI functions (basically a 
  3499.  quick-reference listing of the GPI functions of Warp), and a small section on 
  3500.  how to use the accompanying diskette. 
  3501.  
  3502.  /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3503.  
  3504.  
  3505. ΓòÉΓòÉΓòÉ 10.4. Summary ΓòÉΓòÉΓòÉ
  3506.  
  3507. Summary 
  3508.  
  3509. I like this book a fair amount, and it is a definite improvement on the feel of 
  3510. Stephen Knight's Learning to Program OS/2 2.0 Presentation Manager by Example. 
  3511. At the same time, having only a single sample program has to have its 
  3512. limitations, and I can't help but feel that certain areas could have been 
  3513. covered more in depth.  This does not in any way mean that this book is not a 
  3514. good book, and in fact, one might equally well complain that most books, by 
  3515. having a large number of small programs miss out on the chance to treat certain 
  3516. other subjects in depth.  It is more of a new angle than a bad angle.  I 
  3517. personally prefer more small programs, but I won't let this affect my judgement 
  3518. of the book, because not everyone feels the same way.  I feel that sometimes 
  3519. the reader is left for a long time without concrete code to browse, and other 
  3520. times the code snippets get a little large to digest.  For this reason only, I 
  3521. give this book an A-, rather than an A. 
  3522.  
  3523. /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3524.  
  3525.  
  3526. ΓòÉΓòÉΓòÉ 10.5. Book Reviewed ΓòÉΓòÉΓòÉ
  3527.  
  3528. Book Reviewed 
  3529.  
  3530.      Programming the OS/2 Warp GPI, Knight and Ryan. 
  3531.  
  3532.         -  Wiley and Sons. ISBN 0-471-10718-2. US$39.95, CAN$55.95. 
  3533.         -  OS/2 Graphics Programmers 
  3534.         -  A- 
  3535.  
  3536.       This book should be extremely attractive to anyone writing a graphics 
  3537.       editor, since it includes a capable, if not full-featured graphics editor 
  3538.       program and full source.  It may appeal less to games writers and other 
  3539.       graphics programmers due to the limited nature of using only one sample 
  3540.       application.  Very readable, and well-explained, however. 
  3541.  
  3542.  NOTES 
  3543.  
  3544.  Please note that books aimed at different audiences should only be compared 
  3545.  with great care, if at all.  I intend to concentrate on the strong points of 
  3546.  the books I review, but I will point out any weaknesses in a constructive 
  3547.  manner. 
  3548.  
  3549.  LEGEND 
  3550.  
  3551.  BOOK:  The name of the book, and the author(s) 
  3552.  
  3553.  PUBLISHING INFORMATION:  Publishing company, ISBN, and approximate price. 
  3554.  
  3555.  AUDIENCE:  This is a description of the audience I think the book targets 
  3556.  best.  This is not intended as gospel, just a guideline for people not 
  3557.  familiar with the book. 
  3558.  
  3559.  MARK:  My opinion of the success of the book's presentation, and how well it 
  3560.  targets its audience.  Technical content, accuracy, organization, readability, 
  3561.  and quality of index all weigh heavily here, but the single most important 
  3562.  item is how well the book covers what it says it covers.  Many books try to 
  3563.  cover too much, and get a lower mark as a result. 
  3564.  
  3565.  A+        Ground-breaking, all-around outstanding book. 
  3566.  A         Excellent book. This is what I want to see happen a lot. 
  3567.  A-        Excellent book with minor flaws. 
  3568.  B+        Very good book with minor flaws or omissions. 
  3569.  B         Good book with some flaws and omissions. 
  3570.  B-        Good book, but in need of improvement. 
  3571.  C+        Mediocre book with some potential, but in need of some updating. 
  3572.  C         Mediocre book with some good sections, but badly in need of fixing. 
  3573.  C-        Mediocre book, little good material, desperately in need of an 
  3574.            overhaul. 
  3575.  D         Don't buy this book unless you need it, and nothing else exists. 
  3576.  F         Don't buy this book.  Period. 
  3577.  
  3578.  COMMENTS:  This is a very brief summary of the review proper. 
  3579.  
  3580.  /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3581.  
  3582.  
  3583. ΓòÉΓòÉΓòÉ 10.6. Index ΓòÉΓòÉΓòÉ
  3584.  
  3585. Index 
  3586.  
  3587. This Content Index is designed to let you find the book that covers the topics 
  3588. you need to learn about.  It will eventually have a lot of categories, with 
  3589. each book being rated along each row.  These tables will be quite large, and 
  3590. will continually grow, so please give me your feedback regarding what 
  3591. categories you would like to see, and which you don't.  It may take me a while 
  3592. to flesh them out, so have a little patience. 
  3593.  
  3594. BOOK LEGEND 
  3595.  
  3596. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3597. ΓöéCode ΓöéIssue  ΓöéTitle                                                              Γöé
  3598. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3599. ΓöéRWP  Γöé2-3    ΓöéReal World Programming for OS/2 2.1                                Γöé
  3600. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3601. ΓöéLPE  Γöé2-4    ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example       Γöé
  3602. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3603. ΓöéODD  Γöé2-5    ΓöéWriting OS/2 2.1 Device Drivers in C                               Γöé
  3604. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3605. ΓöéGPI  Γöé2-6    ΓöéOS/2 Presentation Manager GPI                                      Γöé
  3606. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3607. ΓöéTAO  Γöé2-7    ΓöéThe Art of OS/2 2.1 C Programming                                  Γöé
  3608. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3609. ΓöéMOR  Γöé2-8    ΓöéMastering OS/2 REXX                                                Γöé
  3610. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3611. ΓöéRSH  Γöé2-9    ΓöéREXX Reference Summary Handbook                                    Γöé
  3612. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3613. ΓöéADO  Γöé2-10   ΓöéApplication Development Using OS/2 REXX                            Γöé
  3614. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3615. ΓöéPMP  Γöé2-11   ΓöéOS/2 Presentation Manager Programming                              Γöé
  3616. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3617. ΓöéDOA  Γöé3-1    ΓöéDesigning OS/2 Applications                                        Γöé
  3618. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3619. ΓöéOSP  Γöé3-2    ΓöéOS/2 Programming                                                   Γöé
  3620. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3621. ΓöéTGO  Γöé3-4    ΓöéThe GUI-OOUI War                                                   Γöé
  3622. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3623. ΓöéOU   Γöé3-5    ΓöéOS/2 Warp Unleashed, Deluxe Edition                                Γöé
  3624. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3625. ΓöéQR1  Γöé3-6    ΓöéWIN Functions, OS/2 Quick Reference Library Volume 1               Γöé
  3626. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3627. ΓöéPWG  Γöé3-7    ΓöéProgramming the OS/2 Warp Version 3 GPI                            Γöé
  3628. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3629.  
  3630. NOTE:  Books which cover the same material can look similar in this table, but 
  3631. be different in real life.  The style of a book, for example, can not be seen 
  3632. from a quick table, so make sure that you follow up by reading the reviews of 
  3633. the books you find here.  Finally, be sure that the books you are comparing are 
  3634. aimed at the same audiences. 
  3635.  
  3636. PM C BOOKS 
  3637.  
  3638. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3639. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéGPI    ΓöéFonts  ΓöéPrint  Γöé
  3640. Γöé     Γöé     ΓöéBasics ΓöéDriver ΓöéAVIO   ΓöéIntro  Γöé       Γöé       Γöé       Γöé
  3641. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3642. ΓöéRWP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé4      Γöé4      Γöé4      Γöé3      Γöé
  3643. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3644. ΓöéPME  ΓöéB-   Γöé1      Γöé0      Γöé0      Γöé2      Γöé2      Γöé2      Γöé0      Γöé
  3645. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3646. ΓöéODD  ΓöéA    Γöé0      Γöé5      Γöé0      Γöé0      Γöé1      Γöé0      Γöé1      Γöé
  3647. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3648. ΓöéGPI  ΓöéC+   Γöé0      Γöé0      Γöé0      Γöé0      Γöé5      Γöé2      Γöé3      Γöé
  3649. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3650. ΓöéTAO  ΓöéB+   Γöé3      Γöé2      Γöé1      Γöé4      Γöé1      Γöé2      Γöé0      Γöé
  3651. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3652. ΓöéPMP  ΓöéA-   Γöé1      Γöé0      Γöé1      Γöé5      Γöé3      Γöé4      Γöé2      Γöé
  3653. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3654. ΓöéOSP  ΓöéB+   Γöé2      Γöé0      Γöé0      Γöé3      Γöé2      Γöé1      Γöé0      Γöé
  3655. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3656. ΓöéQR1  ΓöéA    Γöé0      Γöé0      Γöé0      Γöé(WIN) 5Γöé0      Γöé0      Γöé0      Γöé
  3657. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3658. ΓöéPWG  ΓöéA-   Γöé0      Γöé0      Γöé0      Γöé1      Γöé5      Γöé5      Γöé5      Γöé
  3659. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3660.  
  3661. REXX BOOKS: 
  3662.  
  3663. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3664. ΓöéBOOK ΓöéMARK ΓöéREXX     ΓöéWPS      ΓöéReferenceΓöé
  3665. Γöé     Γöé     ΓöéIntro    Γöé         Γöé         Γöé
  3666. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3667. ΓöéMOR  ΓöéB    Γöé4        Γöé0        Γöé2        Γöé
  3668. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3669. ΓöéRSH  ΓöéA    Γöé1        Γöé2        Γöé5        Γöé
  3670. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3671. ΓöéADO  ΓöéA-   Γöé3        Γöé2        Γöé4        Γöé
  3672. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3673.  
  3674. SYSTEM AND NON-PROGRAMMING BOOKS: 
  3675.  
  3676. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3677. ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM     ΓöéThread ΓöéGPI    ΓöéFonts  ΓöéPrint  ΓöéWPS    Γöé
  3678. Γöé     Γöé     ΓöéBasics ΓöéDriver ΓöéAVIO   Γöé       Γöé       Γöé       Γöé       Γöé       Γöé       Γöé
  3679. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3680. ΓöéDOA  ΓöéA    Γöé4      Γöé4      Γöé2      Γöé4      Γöé5      Γöé3      Γöé2      Γöé3      Γöé0      Γöé
  3681. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3682. ΓöéTGO  ΓöéB    Γöé0      Γöé0      Γöé0      Γöé2      Γöé1      Γöé0      Γöé2      Γöé1      Γöé5      Γöé
  3683. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3684. ΓöéOU   ΓöéA+   Γöé1      Γöé4      Γöé4      Γöé5      Γöé2      Γöé5      Γöé5      Γöé5      Γöé5      Γöé
  3685. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3686.  
  3687. RATINGS LEGEND: 
  3688.  
  3689. ΓöîΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  3690. Γöé0ΓöéNo coverage           Γöé
  3691. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3692. Γöé1ΓöéVery light coverage   Γöé
  3693. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3694. Γöé2ΓöéIntroductory coverage Γöé
  3695. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3696. Γöé3ΓöéGood Coverage         Γöé
  3697. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3698. Γöé4ΓöéIn-depth coverage     Γöé
  3699. Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  3700. Γöé5ΓöéAuthoritative         Γöé
  3701. ΓööΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  3702.  
  3703. /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3704.  
  3705.  
  3706. ΓòÉΓòÉΓòÉ 10.7. Coming Up ΓòÉΓòÉΓòÉ
  3707.  
  3708. Coming Up 
  3709.  
  3710. I am expecting Reich's new book for next month, but we'll see if it gets here 
  3711. in time.  The following are some other books I intend to review, in no 
  3712. particular order: 
  3713.  
  3714.      Designing High Powered OS/2 Applications, Reich 
  3715.      OS/2 Presentation Manager GPI, 2nd edition, Winn 
  3716.      The Design of OS/2, 2nd Edition, Kogan and Deitel 
  3717.  
  3718.  If anyone has a book they want to see reviewed, I will be happy to oblige. 
  3719.  Just mail me and tell me.  Publishers can send me books at the address on my 
  3720.  personal page at the end of the magazine, and I will review all OS/2 
  3721.  development- related and advanced user books I receive. 
  3722.  
  3723.  /dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3724.  
  3725.  
  3726. ΓòÉΓòÉΓòÉ 11. OOPS Avenue ΓòÉΓòÉΓòÉ
  3727.  
  3728.  
  3729. ΓòÉΓòÉΓòÉ 11.1. Introduction ΓòÉΓòÉΓòÉ
  3730.  
  3731. OOPS Avenue 
  3732.  
  3733. Written by Gordon Zeglinski 
  3734.  
  3735. Introduction 
  3736.  
  3737. There is a new C++ library out called STL (Standardized Template Library).  As 
  3738. the name implies, the library is being standardized and consists of template 
  3739. classes and functions.  There are a couple of versions of STL available.  The 
  3740. easiest (and cheapest) one to get is the HP source code available from 
  3741. butler.hpl.external.hp.com in the /stl directory. 
  3742.  
  3743. So now that you know where to get it, let's take a brief look at it. 
  3744.  
  3745. OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3746.  
  3747.  
  3748. ΓòÉΓòÉΓòÉ 11.2. What Is STL? ΓòÉΓòÉΓòÉ
  3749.  
  3750. What Is STL? 
  3751.  
  3752. STL is a set of template functions and classes that provide a portable compiler 
  3753. neutral toolkit for manipulating and storing data.  Roughly speaking, STL does 
  3754. for "container objects" what the IOSTREAM library does for I/O.  The two 
  3755. implementations of STL that I've looked at were not header file compatible. 
  3756. Thus, one should consider STL still in its infancy. 
  3757.  
  3758. The design of STL is very different from most other container type object 
  3759. classes.  While most use templates, they also use inheritance and virtual 
  3760. functions.  This both affects the performance and the ability to share the 
  3761. object across processes.  Virtual functions are usually implemented as lookup 
  3762. tables attached to the object's instance; when a virtual function is called, 
  3763. its address is pulled from the lookup table.  This address is then used to call 
  3764. the appropriate member function.  If, for example, an instance of an object is 
  3765. created in shared memory, and this object has virtual functions, the lookup 
  3766. table would be filled with addresses of functions belonging to the process that 
  3767. created the instance.  This of course means that only the process creating this 
  3768. instance can use this instance.  Because STL doesn't use virtual functions, 
  3769. this limitation is not present. 
  3770.  
  3771. Another interesting point about the design of STL is that functions to sort, 
  3772. search or otherwise manipulate data are not member functions of the container 
  3773. classes.  This allows the same functions to operate on C-style arrays and C++ 
  3774. based container classes.  The class can be divided into 5 primary components: 
  3775. algorithms, containers, iterators, function objects and adaptors.  Algorithms 
  3776. perform actions such as sorting, searching, merging and the like.  Containers 
  3777. manipulate groups of objects and the memory they require.  Iterators are used 
  3778. to move through a container.  Function objects encapsulate functions use by 
  3779. other parts of the library.  Adaptors provide an alternative interface to a 
  3780. component of the library. 
  3781.  
  3782. OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  3783.  
  3784.  
  3785. ΓòÉΓòÉΓòÉ 11.3. A Simple Program ΓòÉΓòÉΓòÉ
  3786.  
  3787. A Simple Program 
  3788.  
  3789. Let's look at a simple simple test program using standard C-style arrays. The 
  3790. following sample is a modified version of the sort_example.cpp program.  The 
  3791. program was modified to work with C-Set++.  Also note that the STL header file 
  3792. algobase.h had the definitions for min and max commented out to prevent 
  3793. conflict with the min and max macros defined in C-Set++. 
  3794.  
  3795. #include "defalloc.h"
  3796. #include "algo.h"
  3797. #include "tempbuf.cpp"  // Can also just compile and link with this file
  3798. #include "heap.h"
  3799. #include "function.h"
  3800.  
  3801. #include "random.cpp"   // Can also just compile and link with this file
  3802.  
  3803. //Rand is used to fill the array with sequential numbers
  3804. class Rand{
  3805.    int I;
  3806.  
  3807. public:
  3808.    Rand(unsigned long X):I(X){}
  3809.  
  3810.    int operator()(){return I++;}
  3811. };
  3812.  
  3813. void main(int argc, char *argv[]){
  3814.     int    *last1;
  3815.     int    *middle;
  3816.     int     test_sequence1[15];
  3817.  
  3818.     middle = test_sequence1 + 10;
  3819.     last1 = test_sequence1 + 15;
  3820.  
  3821.     ostream_iterator<int> out_stream(cout, " ");
  3822.     less<int> less_than;
  3823.  
  3824.     generate((int*)test_sequence1, last1, Rand(0));
  3825.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3826.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3827.  
  3828.     random_shuffle((int*)test_sequence1, last1);
  3829.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3830.     // Output: (the sequence of 0 through 14 with elements in random order)
  3831.  
  3832.     sort((int*)test_sequence1, last1);
  3833.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3834.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3835.  
  3836.     random_shuffle((int*)test_sequence1, last1);
  3837.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3838.     // Output: (the sequence of 0 through 14 with elements in random order)
  3839.  
  3840.     sort((int*)test_sequence1, last1, less_than);
  3841.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3842.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3843.  
  3844.     random_shuffle((int*)test_sequence1, last1);
  3845.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3846.     // Output: (the sequence of 0 through 14 with elements in random order)
  3847.  
  3848.     stable_sort((int*)test_sequence1, last1);
  3849.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3850.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3851.  
  3852.     random_shuffle((int*)test_sequence1, last1);
  3853.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3854.     // Output: (the sequence of 0 through 14 with elements in random order)
  3855.  
  3856.     stable_sort((int*)test_sequence1, last1, less_than);
  3857.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3858.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3859.  
  3860.     random_shuffle((int*)test_sequence1, last1);
  3861.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3862.     // Output: (the sequence of 0 through 14 with elements in random order)
  3863.  
  3864.     partial_sort((int*)test_sequence1, middle, last1);
  3865.     copy((int*)test_sequence1, last1, out_stream), cout << endl;
  3866.     // Output: 0 1 2 3 4 5 6 7 8 9 1? 1? 1? 1? 1?
  3867.  
  3868. }
  3869.  
  3870. In the above example, last1 and middle are iterators. The array 
  3871. test_sequence1[15] is the container. 
  3872.  
  3873. Basically, the sample involves filling the container, shuffling the elements 
  3874. and then sorting them using the various sort algorithms.  Similarly, one can 
  3875. use a vector container.  A vector container is the closest thing to a C array. 
  3876. The follow example uses a vector instead of an array. 
  3877.  
  3878. #include "defalloc.h"
  3879. #include "algo.h"
  3880. #include "tempbuf.cpp"  // Can also just compile and link with this file
  3881. #include "heap.h"
  3882. #include "function.h"
  3883. #include "vector.h"
  3884.  
  3885. #include "random.cpp"   // Can also just compile and link with this file
  3886.  
  3887. //Rand is used to fill the array with sequential numbers
  3888. class Rand{
  3889.    int I;
  3890.  
  3891. public:
  3892.    Rand(unsigned long X):I(X){}
  3893.  
  3894.    int operator()(){return I++;}
  3895. };
  3896.  
  3897. void main(int argc, char *argv[]){
  3898.     vector<int>::iterator    Start;
  3899.     vector<int>::iterator    last1;
  3900.     vector<int>::iterator    middle;
  3901.     vector<int>              test_sequence1(15);
  3902.  
  3903.     ostream_iterator<int> out_stream(cout, " ");
  3904.     less<int> less_than;
  3905.  
  3906.     Start=test_sequence1.begin();
  3907.     last1 = Start + 15;
  3908.  
  3909.     generate(Start, last1, Rand(0));
  3910.  
  3911.     Start=test_sequence1.begin();
  3912.     middle = Start + 10;
  3913.     last1 = Start + 15;
  3914.  
  3915.     copy(Start, last1, out_stream), cout << endl;
  3916.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3917.  
  3918.     random_shuffle(Start, last1);
  3919.     copy(Start, last1, out_stream), cout << endl;
  3920.     // Output: (the sequence of 0 through 14 with elements in random order)
  3921.  
  3922.     sort(Start, last1);
  3923.     copy(Start, last1, out_stream), cout << endl;
  3924.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3925.  
  3926.     random_shuffle(Start, last1);
  3927.     copy(Start, last1, out_stream), cout << endl;
  3928.     // Output: (the sequence of 0 through 14 with elements in random order)
  3929.  
  3930.     sort(Start, last1, less_than);
  3931.     copy(Start, last1, out_stream), cout << endl;
  3932.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3933.  
  3934.     random_shuffle(Start, last1);
  3935.     copy(Start, last1, out_stream), cout << endl;
  3936.     // Output: (the sequence of 0 through 14 with elements in random order)
  3937.  
  3938.     stable_sort(Start, last1);
  3939.     copy(Start, last1, out_stream), cout << endl;
  3940.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3941.  
  3942.     random_shuffle(Start, last1);
  3943.     copy(Start, last1, out_stream), cout << endl;
  3944.     // Output: (the sequence of 0 through 14 with elements in random order)
  3945.  
  3946.     stable_sort(Start, last1, less_than);
  3947.     copy(Start, last1, out_stream), cout << endl;
  3948.     // Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
  3949.  
  3950.  
  3951.     random_shuffle(Start, last1);
  3952.     copy(Start, last1, out_stream), cout << endl;
  3953.     // Output: (the sequence of 0 through 14 with elements in random order)
  3954.  
  3955.     partial_sort(Start, middle, last1);
  3956.     copy(Start, last1, out_stream), cout << endl;
  3957.     // Output: 0 1 2 3 4 5 6 7 8 9 1? 1? 1? 1? 1?
  3958. }
  3959.  
  3960. As before, last1 and middle are iterators.  The container is test_sequence1. 
  3961. However, a new iterator called Start is introduced.  In the first example, the 
  3962. container could double as the starting iterator because the container was 
  3963. simply a pointer. In the second sample, the container is a vector class.  The 
  3964. vector class can't act as an iterator so we use Start.  In our last example, we 
  3965. will use the set manipulation functions to create a vector based upon 2 other 
  3966. vectors. 
  3967.  
  3968. typedef vector<int> IVec;
  3969.  
  3970. void main(int argc, char *argv[]){
  3971.    vector<int> Set1,Set2,Output;
  3972.  
  3973.    ostream_iterator<int> out_stream(cout, " ");
  3974.    less<int> less_than;
  3975.  
  3976.    //let's insert some values at the END
  3977.    // of the vector
  3978.    Set1.insert(Set1.end(),10);
  3979.    Set1.insert(Set1.end(),11);
  3980.    Set1.insert(Set1.end(),2);
  3981.    Set1.insert(Set1.end(),1);
  3982.    Set1.insert(Set1.end(),12);
  3983.    Set1.insert(Set1.end(),5);
  3984.  
  3985.    Set2.insert(Set2.end(),10);
  3986.    Set2.insert(Set2.end(),5);
  3987.    Set2.insert(Set2.end(),2);
  3988.    Set2.insert(Set2.end(),20);
  3989.    Set2.insert(Set2.end(),24);
  3990.  
  3991.    //let's display our two vectors
  3992.    cout<<"Set 1"<<endl;
  3993.    copy(Set1.begin(),Set1.end(), out_stream), cout << endl;
  3994.    cout<<"Set 2"<<endl;
  3995.    copy(Set2.begin(),Set2.end(), out_stream), cout << endl;
  3996.  
  3997.    //set operations work on sorted containers.. sooo
  3998.    //let's sort these puppies and then display them..
  3999.  
  4000.    sort(Set1.begin(),Set1.end());
  4001.    cout<<"Set 1 Sorted"<<endl;
  4002.    copy(Set1.begin(),Set1.end(), out_stream), cout << endl;
  4003.  
  4004.    sort(Set2.begin(),Set2.end());
  4005.    cout<<"Set 2 Sorted"<<endl;
  4006.    copy(Set2.begin(),Set2.end(), out_stream), cout << endl;
  4007.  
  4008.    //let's get the union and put it in the Output vector
  4009.  
  4010.    set_union(Set1.begin(),
  4011.              Set1.end(),
  4012.              Set2.begin(),
  4013.              Set2.end(),
  4014.              insert_iterator<IVec>(Output,Output.begin()));
  4015.    cout<<"Union"<<endl;
  4016.  
  4017.    //display the output vector
  4018.    copy(Output.begin(),Output.end(), out_stream), cout << endl;
  4019.  
  4020.    //display the result
  4021.    Output.erase(Output.begin(), Output.end());
  4022.  
  4023.    //get the intersection
  4024.    set_intersection(Set1.begin(),
  4025.                     Set1.end(),
  4026.                     Set2.begin(),
  4027.                     Set2.end(),
  4028.                     insert_iterator<IVec>(Output,Output.begin()));
  4029.    cout<<"Intersection"<<endl;
  4030.    copy(Output.begin(),Output.end(), out_stream), cout << endl;
  4031.  
  4032.    Output.erase(Output.begin(), Output.end());
  4033.  
  4034.    //lets find the difference between set1 and set2
  4035.    set_difference(Set1.begin(),
  4036.                   Set1.end(),
  4037.                   Set2.begin(),
  4038.                   Set2.end (),
  4039.                   insert_iterator<IVec>(Output,Output.begin()));
  4040.    cout<<"Difference Set1 <-> Set2"<<endl;
  4041.    copy(Output.begin(),Output.end(), out_stream), cout << endl;
  4042.    Output.erase(Output.begin(), Output.end());
  4043.  
  4044.    //lets find the difference between set2 and set1
  4045.    set_difference(Set2.begin(),
  4046.                   Set2.end(),
  4047.                   Set1.begin(),
  4048.                   Set1.end (),
  4049.                   insert_iterator<IVec>(Output,Output.begin()));
  4050.    cout<<"Difference Set2 <-> Set1"<<endl;
  4051.    copy(Output.begin(),Output.end(), out_stream), cout << endl;
  4052. }
  4053.  
  4054. An interesting point worth noting is that the set_* functions use iterators to 
  4055. determine where the results of the set operations go. There's no reason the 
  4056. output couldn't have been sent directly to the display instead of to the Output 
  4057. vector.  This is left as an exercise for the curious. 
  4058.  
  4059. OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4060.  
  4061.  
  4062. ΓòÉΓòÉΓòÉ 11.4. Wrapping Things Up ΓòÉΓòÉΓòÉ
  4063.  
  4064. Wrapping Things Up 
  4065.  
  4066. Well that's about it for our quick look at STL.  The files arraysort.cpp, 
  4067. vecsort.cpp and vecunion.cpp are included if you wish to try and compile the 
  4068. sample programs.  Note the HP STL release may not compile on your particular 
  4069. C++ compiler.  It requires a very accurate template implementation to work. 
  4070.  
  4071. Coming up in future issues, we'll be looking at various OS/2 C++ compilers. 
  4072. We'll be using STL as part of our compiler testing. 
  4073.  
  4074. OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4075.  
  4076.  
  4077. ΓòÉΓòÉΓòÉ 12. Contributors to this Issue ΓòÉΓòÉΓòÉ
  4078.  
  4079. Are You a Potential Author? 
  4080.  
  4081. We are always looking for (new) authors.  If you have a topic about which you 
  4082. would like to write, send a brief description of the topic electronically to 
  4083. any of the editors, whose addresses are listed below, by the 15th of the month 
  4084. before the month in which your article will appear.  This alerts us that you 
  4085. will be sending an article so that we can plan the issue layout accordingly. 
  4086. After you have done this, get the latest copy of the Article Submission 
  4087. Guidelines from hobbes.nmsu.edu in the /os2/newsltr directory.  (The file is 
  4088. artsub.zip.) The completed text of your article should be sent to us no later 
  4089. than five days prior to the last day of the month; any articles received after 
  4090. that time may be pushed to the next issue. 
  4091.  
  4092. The editors can be reached at the following email addresses: 
  4093.  
  4094.      Larry Salomon - os2man@panix.com (Internet). 
  4095.      Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet). 
  4096.  
  4097.  The following people contributed to this issue in one form or another (in 
  4098.  alphabetical order): 
  4099.  
  4100.      Mike Duffy 
  4101.      Juergen Riedl 
  4102.      Larry Salomon, Jr. 
  4103.      Holger Veit 
  4104.      Carsten Whimster 
  4105.      Gordon Zeglinski 
  4106.      Network distributors 
  4107.  
  4108.  Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4109.  
  4110.  
  4111. ΓòÉΓòÉΓòÉ 12.1. Michael T. Duffy ΓòÉΓòÉΓòÉ
  4112.  
  4113. Michael T. Duffy 
  4114.  
  4115. Michael is a recent graduate of the University of Southern California and has 
  4116. degrees in Cinema Production and East Asian Languages and Cultures.  His 
  4117. computer skills are self-taught, and he has been programming for OS/2 since 
  4118. about December of 1994.  Michael is working on breaking into the game 
  4119. development industry, and has been working towards that goal for a number of 
  4120. months.  He expects to release his first game, an OS/2 shooter, later this 
  4121. year. 
  4122.  
  4123. Michael can be reached on the internet at mduffy@ionet.net. 
  4124.  
  4125.  
  4126. ΓòÉΓòÉΓòÉ 12.2. Juergen Riedl ΓòÉΓòÉΓòÉ
  4127.  
  4128. Juergen Riedl 
  4129.  
  4130. Juergen Riedl is physicist and has studied at the Ludwig Maximilians University 
  4131. of Munich / Germany / Bavaria.  He is a system engineer at Siemens Nixdorf 
  4132. Informationsystems and currently working on information models for SDH high 
  4133. bandwidth management systems.  All programming is self- taught; he has been 
  4134. programming OS/2 applications since the release of OS/2 2.0.  When he is not 
  4135. doing OS/2 he can be found in summer in the Alps sailplaning or in the winter 
  4136. rigging up his model railway. 
  4137.  
  4138. Juergen can be reached at j.riedl@mch.sni.de. 
  4139.  
  4140.  
  4141. ΓòÉΓòÉΓòÉ 12.3. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
  4142.  
  4143. Larry Salomon Jr. 
  4144.  
  4145. Larry Salomon Jr. has been developing OS/2 applications since version 1.1 in 
  4146. 1989.  He has written numerous applications, including the Scramble applet that 
  4147. was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen 
  4148. Capture trio that has been distributed on numerous CD-ROMs. 
  4149.  
  4150. Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C 
  4151. Programming (Wiley-QED).  Finally, he is the CEO/President of IQPac Inc. which 
  4152. is responsible for the publication of EDM/2 and he is a frequent contributor to 
  4153. the publication. 
  4154.  
  4155. Larry can be reached electronically via the Internet at os2man@panix.com. 
  4156.  
  4157. Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4158.  
  4159.  
  4160. ΓòÉΓòÉΓòÉ 12.4. Holger Veit ΓòÉΓòÉΓòÉ
  4161.  
  4162. Holger Veit 
  4163.  
  4164. Holger Veit studied electrical engineering and also holds a PhD degree in this 
  4165. area (testing of digital circuits).  He is currently working as a senior 
  4166. researcher at the GMD (German National Research Center for Information 
  4167. Technology) where he is developing CAD methodologies for designing mixed 
  4168. hardware and software systems.  His interest in OS/2 is almost a private 
  4169. pleasure, but he has several years of detailed experience (down to the 
  4170. motherboard level) with operating systems like BSD and OS/2. 
  4171.  
  4172. He can be reached via e-mail at holger.veit@gmd.de. 
  4173.  
  4174.  
  4175. ΓòÉΓòÉΓòÉ 12.5. Carsten Whimster ΓòÉΓòÉΓòÉ
  4176.  
  4177. Carsten Whimster 
  4178.  
  4179. Carsten is an undergraduate Computer Science student at the University of 
  4180. Waterloo.  He is currently in fourth year, and enjoying it immensely.  He uses 
  4181. Watcom C/C++ 10.0a and Watcom VX-REXX 2.0b.  Carsten is the author of some 
  4182. commandline utilities, and POV-Panel/2.  He is currently trying to learn enough 
  4183. GPI programming to do a remake of the old video game Qix.  He is also a 
  4184. TEAM-OS/2 member, and has adopted a little computer store called The Data Store 
  4185. in Waterloo, Ontario, which promptly hired him part-time. 
  4186.  
  4187. You may reach Carsten... 
  4188.  
  4189. ...via email: 
  4190.  
  4191. bcrwhims@undergrad.math.uwaterloo.ca - Internet 
  4192.  
  4193. ...World Wide Web homepage (incomplete; aren't they all): 
  4194.  
  4195. http://www.undergrad.math.uwaterloo.ca/~bcrwhims - WWW 
  4196.  
  4197. ...via snail mail: 
  4198.  
  4199. Carsten Whimster
  4200. 318A Spruce Street
  4201. Waterloo, Ontario
  4202. Canada
  4203. N2L 3M7
  4204.  
  4205. ...via phone 
  4206.  
  4207. (519) 886-2439 
  4208.  
  4209. Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4210.  
  4211.  
  4212. ΓòÉΓòÉΓòÉ 12.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
  4213.  
  4214. Gordon Zeglinski 
  4215.  
  4216. Gordon Zeglinski is a freelance programmer/consultant who received his Master's 
  4217. degree in Mechanical Engineering with a thesis on C++ sparse matrix objects. 
  4218. He has been programming in C++ for 6 years and also has a strong background in 
  4219. FORTRAN.  He started developing OS/2 applications with version 2.0 . 
  4220.  
  4221. His current projects include a client/server communications program that 
  4222. utilitizes OS/2's features which has entered beta testing.  Additionally, he is 
  4223. involved in the development of a "real-time" automated vehicle based on OS/2 
  4224. and using C++ in which he does device driver development and designs the 
  4225. applications that comprise the control logic and user interface. 
  4226.  
  4227. He can be reached via the Internet at zeglins@cc.umanitoba.ca. 
  4228.  
  4229. Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7 
  4230.  
  4231.  
  4232. ΓòÉΓòÉΓòÉ 12.7. Network distributors ΓòÉΓòÉΓòÉ
  4233.  
  4234. Network Distributors 
  4235.  
  4236. These people are part of our distribution system to provide EDM/2 on networks 
  4237. other than the Internet.  Their help to provide access to this magazine for 
  4238. others is voluntary and we appreciate them a lot! 
  4239.  
  4240.      Paul Hethmon (phethmon@utk.edu) - Compuserve 
  4241.      Gess Shankar (gess@knex.mind.org) - Internet 
  4242.      Jason B. Tiller (PeerGynt@aol.com) - America On-line 
  4243.      David Singer (singer@almaden.ibm.com) - IBM Internal 
  4244.      Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's 
  4245.  
  4246.  If you would like to become a "network distributor", be sure to contact the 
  4247.  editors so that we can give you the credit you deserve! 
  4248.  
  4249.  Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7