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 >
Wrap
OS/2 Help File
|
1995-08-03
|
456KB
|
4,249 lines
ΓòÉΓòÉΓòÉ 1. Aug 1995 Title Page ΓòÉΓòÉΓòÉ
The Electronic Developer's Magazine for OS/2
Portions copyright (c) by IQPac Inc.
Volume 3, issue 7
Administrivia
There has to be a section of Murphy's law's that deal with computers and
specifically with making announcements. Immediately after announcing the EDM/2
Web site, the address changed and EDM/2 missed the next issue. The new URL is
http://os2man.netsysdev.telerate.com . Ah, what three letters can do to a
person.
The Web site is growing nicely. A Gotcha section has been added which will
grow into a repository of programming pitfalls, and it utilizes HTML forms to
allow you to contribute directly to the page. Additionally, a weekly From the
editor section was added to allow me to tell you about things that you should
know as an OS/2 developer in a more timely fashion. Let's face it; if you read
things once a month here, there's a good chance that the information is no
longer valid by that time. Finally, a Feedback section was added to give you
the opportunity to sound off; tell us what you think about anything. We'll be
glad for your feedback.
In any case, as we get more time, more things will get updated so keep a
lookout and send us any feedback you have!
Errata
Last issue's article on IPC Between DOS Processes was incorrectly described as
having been authored by Mike Ruddy. It was instead written by Leif N. Eriksen.
Infoworld, Brian Livingston, et al.
Those of you who are fortunate enough to read Infoworld on a regular basis
probably know who Brian Livingston is - he is a "pro-Windows and everything
else can go to hell" kind of a person - but in his July 24 column, he said
something quite upsetting. Paraphrased, "if you are one of the 3 people who
don't have a preview copy of Windows 95..." I've seen this attitude before and
always make sure I send off some email to correct the situation; this time was
no different. I told Brian that I've been using OS/2 since 1989 and have been
quite happy with it. I have had no reason nor desire to go to Windows and
probably never will. I selected the "Send" button and figured that was that.
Boy was I wrong.
His response was infuriating. Not only did he insult me by telling me that I
should be saving his columns for the general availability of Windows 95, but he
added "salt to the wound" by telling me in a post script that "the other two
people also complained."
In the words of Bugs Bunny, "this means war."
My reply to him can be found in the From the editor section for the week
beginning July 24. The only thing I request is, if you are like me and are
happy with OS/2, that you drop him a line to tell him so. His email address is
brian_livingston@infoworld.com . I am not encouraging you to flame him to a
cinder. Simply let him know which operating system you will use on August 24.
The amount of mail coming into his mailbox should help him to adjust his
opinion.
Stewart Alsop, on the other hand, always seems to come on strong in his
columns. While I won't deny that he has a bite, he did surprise me also this
past week. I have had email "discussions" (more like me venting a bit of
frustration at him) with him and have always considered him to be another
Windows bigot. I told him this in a recent email to which he responded, again
paraphrasing, "that is an amusing concept." He enforced that with the claim
that he has used a Mac since 1985, a fact I did not remember until after I read
that. Well, at least I can't claim that he's so anti-IBM because he's so
pro-Windows. Maybe there is a bit of objectivity in him after all...
And Nicholas Petreley has to be out on a limb there. He's the only vocal
pro-OS/2 writer there (the keyword is "vocal") and that has to be stressful.
Help him out, people; if you know of some hot new product or development tool,
let him know about it. He'll thank you for it, guaranteed. His address is
nicholas_petreley@infoworld.com .
It's That Time Again
Gordon will, starting this issue, begin another round of C++ compiler
comparisons, and he definitely has some interesting things to tell you. He
plans to review two compilers per month, but that will depend on his schedule
in future months. A related note is that, because this issue is quite large
due to the screen shots included in the compiler review, the Introduction to PM
Programming column will not be a part of this month's issue.
...And Speaking of Reviewing
I have received a couple of tentative offers from people willing to try to be
our Software Review columnist. If you are interested, simply let me know; the
only commitment you have to keep is to review one development-related
application per month.
Spread the Word
If you haven't visited the #os/2 channel on IRC yet, it's about time you did.
There are IRC clients for most platforms and it isn't really that addicting
<grin>. In #os/2, you can get your questions answered about configuration
problems, user problems, and even programming problems. It's helpful for the
"I need the answer now" problem. Some problems go unanswered but it's always
worth a try, and the "regulars" are great fun. I'm always in there (with the
nickname of Q--, unsurprisingly) and so are many other very knowledgeable
people.
Please Wait Another Month
I made a promise in June to demonstrate how to make transparent windows, but
this month has kept me quite busy, and I will continue to be so until August
15, when the ColoradOS/2 presentations are due to Wayne Kovsky. In fact, if I
hadn't cancelled last month's issue, I would have done so this month. Please
be patient; I will fulfill this promise next issue.
One Final Note
This is wrong, but I'm going to say it anyway: the 2nd edition of my book
should hit the shelves in the U.S. on approximately September 1, according to
John Wiley and Sons. It is entitled, The Art of OS/2 Warp Programming. If you
want more information, stop by the "official" web site, also located at
http://os2man.netsysdev.telerate.com.
Enjoy this issue!
ΓòÉΓòÉΓòÉ 2. Copyright Notice ΓòÉΓòÉΓòÉ
Copyright Notice
EDM/2 is published by IQPac Inc. IQPac Inc. can be reached via U.S. Mail at
the following address:
IQPac Inc.
7 East Broadway, Box 804
New York, NY 10038
U.S.A.
Editor-in-chief Larry Salomon Jr.
Associate editor Carsten Whimster
Contributing editor Gordon Zeglinski
CEO/President Larry Salomon Jr.
All material is copyrighted by its original author. No part of this magazine
may be reproduced without permission from the original author.
This publication may be freely distributed in electronic form provided that
all parts are present in their original unmodified form. A reasonable fee may
be charged for the physical act of distribution; no fee may be charged for the
publication itself.
Neither IQPac Inc. nor this publication are affiliated with International
Business Machines Corporation.
OS/2 is a registered trademark of International Business Machines Corporation.
Other trademarks are property of their respective owners. Any mention of a
product in this publication does not constitute an endorsement or affiliation
unless specifically stated in the text.
The OS/2 Accredited Logo is a trademark of International Business Machines
Corporation and is used by IQPac Inc. under license. This On-line Publication
is independently produced by IQPac Inc. and IBM is not responsible in any way
for its contents.
IQPac Inc. is an accredited member of the IBM Independent Vendor League.
Copyright Notice - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 3. Letters ΓòÉΓòÉΓòÉ
Letters
To write to EDM/2, send your email to os2man@panix.com and use the Subject:
line "Letters".
'Games' Was A Hit
Lachlan O'Dea (drizzt@cc.monash.edu.au) writes:
Thank you for your excelent Gearing Up For Games article in EDM/2. It was very
interesting and easy to understand. I'm a good programmer, but I'm relatively
new to OS/2 and I've never touched DIVE.
I look forward to future articles by you on game programming in OS/2. EDM/2
keeps getting better and better!
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
...So Was 'EXE Optimization'
Steve Snyder (ssnyder@icon-stl.net) writes:
Having just read your very good articles on EXE optimization ("Building Smaller
OS/2 Executables", EDM issues 3-3 and 3-4), I have a question.
It concerns the use of the LINK386 /BASE switch. You state that the use of
/BASE:0x10000 eliminates the need for fixups, making the EXE smaller and the
loading of it faster. I tried it on my program and in fact the 1.5MB EXE size
shrunk by 80k!
Now my question: Is there a downside to using this switch? If not, I don't
understand why IBM did not make this the default. This looks so much like a
free lunch that I'm looking for the hidden cost.
Thanks for the informative articles.
Pete Cassetta responds:
Thanks for your nice comments about my articles.
I was very glad to hear that your 1.5 MB EXE shrunk by 80K when you began using
the /BASE:0x10000 linker switch! I suppose this switch does sound like
something for nothing, but in this case you can have a free lunch. There is
absolutely no downside to using this switch. If you benchmark your program
carefully, you should see an improvement in load time as well. This switch
simply causes the linker to resolve internal fixups at link time instead of
leaving them in there to be resolved at load time. OS/2 allows this because
its designers wisely decided that all EXEs would load at a base address of
0x10000. Hence the load address is always known at link time.
The question of why LINK386 doesn't use /BASE:0x10000 by default for EXEs is a
good one. I really don't know the answer, though I imagine there must be some
historical or philisophical reason. You may be interested to know that the
authors of C-Set++ agree with you that this switch should be on by default. If
you compile and link by calling the ICC program that comes with C-Set++, it
turns on the /BASE:0x10000 switch by default when calling LINK386. ICC actually
turns on three size-related switches by default:
/align:16 /exepack /base:65536 (taken from an ICC-generated command-line)
Because of this, many programs built with C-Set++ get these switches turned on
with no explicit effort on the part of their author. If you are using C-Set++,
then I expect you wrote your own makefile which calls LINK386 directly. In
this case you have to turn on the /BASE switch yourself.
So don't fear the /BASE:0x10000 switch; it is a friend and should be used when
linking all your EXE files.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
A Request or Two
Paul D. Walker (pdwalker@hk.super.net) writes:
I have looked forward to the 'zine since I first discovered and read all the
issues last year. I have enjoyed the publication as, I am sure, many others
have. Since you did not receive any letters last month, I thought that I would
at least break the silence and give you my support (whoopee!) Well, enough of
that.
What I would like to see is either a continuation of installable file systems
(and the nuts and bolts of how to), or something on the internals (as far as
anyone can find out) of HPFS.
In general, I have found the third year of your publication (so far) to be the
best yet. I especially enjoyed the articles on reducing code size, especially
with todays programs getting bloated beyond everything imaginable (my simple
clipper programs frequently go over 700KB nowadays because of the overhead of
my library on top of clippers library.)
Please keep up the good work. Please continue your introduction to PM
programming (as one day soon I will go back and read all the articles and start
programming under OS/2 myself...or wait for Visual Age (*grin*) and any other
topic that you might be interested in yourself. If you are interested in a
particular thing, then you can bet that someone else will be. (At least that
is what an older more experienced DJ told me years ago when I was learning the
trade...)
Looking forward to the next issue...
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Dirk Wissmann (wissmann@genesis.westend.com) writes:
I absolutely appreciate your EDM/2 and I like the articles written there.
Especially the "Introduction to PM Programming" is a favourite one, which I
always read to increase my knowledge.
But now I have reached the point where I have to use something, that was
covered in no issue until now (including Vol. 3 Iss. 6): creation and handling
of notebooks.
When looking on the themes which were published in the section PM Programming,
almost everything was important. And in my opinion, creating a notebook is as
important as all the other themes - just think about making your PM application
configurable.
So how about this theme? Will this be something for an EDM/2 in the near
future, or will it take a longer time until it will show up?
Larry Salomon responds:
As you might imagine, EDM/2 is dependent on the voluntary works of the
contributors, so we cannot give a satisfactory answer since we do not know who
will be submitting what. While I would love to get to the "meat" of things in
the column, I want to avoid rushing the column since I felt that was a
significant problem with the first effort at it. PM programming is quite
difficult; rushing things would leave out significant details in all likelihood
and might confuse the readers.
Your feedback has been noted, however, and I will try to fish for someone to
write an article on this topic.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Solving a Programming Problem
Mark Mathews (mmathews@genesis.nred.ma.us) writes:
I'm slowly porting DEU 5.3 (DOOM editor. DOOM? What's DOOM? <grin>) over to
OS/2. It's now drawing maps. I'm trying to figure out how to use mouse
messages. I tried using WM_BUTTON1CLICK and WM_BUTTON2CLICK but if I try to
double click the mouse I still activate the WM_BUTTON1CLICK. What I want to do
is to click once to mark an object on the map or to click twice and edit the
object. I don't have to mark an object to edit it. 'Mark' is used to select
more than 1 item. So how do I distinguish between all these different mouse
messages?
Larry Salomon responds:
There is no way to automatically do it, so you have to use some voodoo magic to
get what you want. When you get the WM_BUTTON1CLICK message, call
WinQuerySysValue(HWND_DESKTOP,SV_DBLCLKTIME) and start a timer (WinStartTimer)
with the value returned. If you get a WM_BUTTON1DBLCLK message before you get
the appropriate WM_TIMER message, then you process the "double click event"
otherwise you process the "single click event".
Don't forget to call WinStopTimer!
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
cdray@icis.on.ca writes:
I've used just about every PM control (including containers) with great
success, but it may be the lowly Button control which finally drives me insane.
My particular problem is with the BS_BITMAP style. I have used the BS_ICON
style with no problem. I am attempting to create a button, with bitmap, in the
client area of my main window using WinCreateWindow. When I specify BS_ICON
and the appropriate .ICO file, the button is displayed and functions correctly.
When I specify BS_BITMAP and a .BMP file, nothing is displayed.
Any help would be greatly appreciated!
Larry Salomon responds:
This was a bug in the 2.x toolkit. Are you using that or the Warp toolkit? I
haven't verified the "fix" that I have hoped for in the latter.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Web Site Feedback
Kevin Porter (kporter@nmia.com) writes:
This may be beyond your control but an "expand all" button when reading the
magazine would be very helpful, since there's a significant delay each time an
expand is done.
It's nice to find the stuff on-line, i've been off the distribution since my
account moved a while ago and it's nice to see your work continuing/maturing.
Hope it's going well for you. Keep up the good work!
EDM/2 responds:
Thanks for the compliments and comments. We are held hostage by Peter Childs,
the author of the INF-HTML package until we get time to convert the issues to
HTML format directly.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Mark Noble (mnoble@ukanvm.cc.ukans.edu) writes:
The EDM/2 WWW setup is well done, however there's one thing that I'd like to
see. I don't know what's involved in this, but if it isn't to difficult, is
there any way you could "gather" all of the Q&A sections into one page? If the
load on the server gets a little high, this might help.
[Editor's note - Mark did this for us, but we have been too busy to incorporate
it into the Web site.]
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Documentation Error
jrb@mfltd.co.uk writes:
I received the info doc telling me how to subscribe to EDM/2 and where to find
the back issues via FTP. I think the location is wrong and needs updating:
It said hobbes.nmsu.edu /pub/os2/32bit/program/newsltr, but I found it in
/os2/newsltr instead.
EDM/2 responds:
Was this doc obtained from the mail server (edm2-info@knex.mind.org) or from
some other location? If the former, it should have been changed by now, so you
might re- request it to check. If from some other location, I have no control
over this, but you could send email to the site admin and tell them to get the
document again.
Thanks for pointing this out.
Letters - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 4. Announcements ΓòÉΓòÉΓòÉ
Announcements
Learn REXX with The REXX Cookbook and The Rexx Files
Author: Merrill Callaway
Publisher:
Whitestone
511-A Girard Blvd SE
Albuquerque, NM 87106 USA
(505) 268-0678
email 5979987@mcimail.com
Product Description and Ordering Information
The REXX Cookbook is a unique tutorial designed to teach anyone, even
non-programmers, to program in REXX by presenting detailed explanations of over
40 useful REXX programs. These programs and several more are on the companion
disk THE REXX FILES. Those who have experienced the frustration of trying to
write real world code after finding only fragmentary examples in reference
books will really appreciate the programs in this book.
Charles Daney of Quercus Systems and author of Programming in REXX, published
by McGraw Hill, had this to say to Mr. Callaway after he reviewed it:
"I was really impressed with the amount of work you put in on this. It's one
of the most detailed computer books I've ever seen, and not just trivial detail
either, but good solid information. And some of your examples are among the
best I've seen anywhere. The stuff on PostScript, SQL, DB2/2, AmiPro, etc.
should be really valuable to many."
Callaway works from the premise that reference books on programming have too
high a degree of abstraction and generalization to be tutorials, since they
attempt to cover every case for every instruction. Learners must decipher
templates and syntax diagrams rather than view explicit code in the context of
a complete, concrete program. His book makes learning REXX far easier than
ever before, because readers can see actual code used and explained in context.
It is a bonus that the book's programs are so useful in their own right. There
was as much software development as writing to produce this book. For instance
one example project is an Inter-Process Control REXX program that combines
VX-REXX by WATCOM, REXX and DB2/2 by IBM, and AmiPro by Lotus Development.
Another unique program uses REXX and PostScript together to print envelopes
quickly without needing to open a word processor. It even keeps a database of
your personal addresses handy. There are some essential system utility
programs to back up your .INI files, some EPM and TSPF editor macros, and even
a program to teach you how to use the parse instruction. The level of
difficulty is graduated so the book is suitable for beginners and experts
alike. Everyone will find useful REXX code in The REXX Cookbook. Combined
with any standard or online REXX reference, it rounds out a COMPLETE COURSE in
REXX FLUENCY. Callaway says, "The REXX Cookbook is the very book I wished I'd
had when I was learning to program in REXX!"
The REXX Cookbook is OS/2 Accredited.
How to order
VISA/MasterCard orders may email or telephone with credit card number and
expiration date.
Checks or money orders (made payable to Whitestone) US Bank in US dollars are
also acceptable (mail to publisher's address above).
Price: Deluxe Set (book and disk): $42.90 (book ONLY: $27.95)
Shipping and handling USA: $5.00
Shipping and handling elsewhere: $12.00
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Mindy Ported to OS/2
I have completed a port of Mindy 1.3 to OS/2.
Mindy is an implementation of the Dylan language but Mindy is not Dylan yet.
Dylan is a general-purpose Object Oriented Dynamic Language designed by Apple
Computer.
Quoting from Apple's Dylan Home Page at
http://www.cambridge.apple.com/dylan/dylan.html:
"Dylan is a new language developed at Apple. It is a bold new effort to create
a powerful, practical tool for writing mainstream commercial applications. We
believe it combines the best qualities of static languages (small, fast
programs) with the best qualities of dynamic languages (rapid development, code
that's easy to read, write and maintain)."
Credits for Mindy, and therefore 99% of this port, go to the Gwydion Project at
Carnegie Mellon University.
Mindy is freely available and the modified source and executables have been
uploaded to hobbes.nmsu.edu. The file is named mindy13.zip and it should be in
the /os2/dev32/ directory. While you are there, get /os2/unix/emx09a/emxrt.zip
if you don't have it. It contains DLLs required by the Mindy executables.
hobbes.nmsu.edu is mirrored at ftp.cdrom.com in /pub/os2/. I only tested the
port under OS/2 Warp.
The Gwydion project released Mindy 1.3 but please send bug reports to me if you
use this port. They have much better things to do than fix my bugs. <grin>
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Introduction to OS/2 Programming in C Course
From Distributed Systems Laboratories Education Services
The five day course, Introduction to OS/2 Programming in C, is now available.
DSL can schedule this course at your site, or provide materials under a license
agreement. Rates are determined by volume and location (Country). All courses
are taught in English, although translation services are available.
The Intro to OS/2 Programming course will begin a complete OS/2 series of
courses, including Advanced OS/2 Programming, Intro to PM Programming, and
Advanced PM Programming.
Other courses already available include a two day Intro to OS/2, Overview of
Object-Oriented Analysis and Design, C/C++ Programming, DCE Architecture and
Internals, UNIX System Optimization and Performance Evaluation, UNIX System
calls, Borland's Delphi, and more.
Introduction to OS/2 Programming in C
Course Overview
This five day, instructor-lead course will provide an introduction to
programming under IBM's OS/2 operating system, v2.x and higher. The majority
of the class will be spent in laboratory exercises, interspersed with lecture
and examples. This course provides the beginning concepts which are followed
up in the Advanced OS/2 programming course, and the Presentation Manager
Programming courses. As a prerequisite, all students must know and have
experience with the C programming language. Familiarity with the Workplace
Shell, from a user standpoint, is helpful.
Students are welcome to bring a copy of their own source code editor. The
standard OS/2 'E' and 'EPM' editors will be provided.
Target Audience
The target audience for this course is Application and System software
developers, designers, and maintainers.
Course Objectives
This course will provide the student with technical and practical experience
with:
Multi-threaded programming
The OS/2 Control Program API
File and Disk Handling
Timing Events
Dynamic Memory
Semaphores and Queues
Dynamic Link Libraries
For more information, or to schedule a course, contact Gregory Bryant at
800-890-8676, 513-698-5108, or fax 513-698- 4490.
Distributed Systems Laboratories is a division of Delta Music Systems, Inc.
(OS/2 is a registered trademark of IBM Corporation.)
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
SpeedPascal/2 version 1.0
SpeedPascal/2 is a Borland Pascal 7.0 compatible compiler and an integrated
development environment (IDE) with a host of features designed to ease the
task of writing OS/2 Presentation Manager(TM) programs. At last, you can use
the productive programmer's language of choice on the world's most productive
operating system:
NO runtime royalites!
NO huge support .DLLs!
NO lengthy compile times for small programs!
NO sluggish interpreted code!
NO limits!
The SpeedPascal/2 environment is a suite of tools centered around a Multiple
Document Interface editor. From the IDE, you can access the power of the
SpeedPascal/2 tools:
A PM-based MDI editor
An integrated debugger
A 32-bit OS/2 compiler
An OS/2 Assembler
A Resource Editor and Compiler
An Inline Assembler
Context sensitive help
We're pretty proud of our IDE here at SpeedSoft. If you prefer to use your
own editor, that's fine with us. You still have access to the tools you need:
A command line compiler
A command line assembler
A standalone resource editor
A command line resource compiler
SpeedPascal comes complete with electronic versions of:
The User's Manual
The Programmer's Manual
The SpeedPascal/2 Language Reference
The OPML Reference Manual
SpeedPascal/2 additionally comes with sample code demonstrating the features
of the compiler and OS/2.
SpeedPascal/2 for OS/2 is just the beginning for SpeedSoft. We're committed
to being a cross-platform solution, and to providing you with the best tools
around for any platform. We're currently at work with major vendors of Pascal
products to see that your favorite libraries get ported to SpeedPascal/2.
More info:
Download the information brochure at:
Compuserve: OS2DF1 forum, REXX/Other, file SPDBRO.TXT
WWW: http://xs4all.nl/~atverm/index.html
Demo Available
A completely functional demo version is available at the same Compuserve forum
and through the Web page. The demo can also be downloaded by anonymous ftp at
130.112.6.2, change to the OS2 directoy and transfer (in binary mode) the file
speedos2.zip.
Limited Time Offer
From now until July 31st, 1995, SpeedSoft is offering the SpeedPascal/2
compiler for the price of $129! (Sorry, we can't discount the manual
hardcopies.) After this period the price will be $179.
SpeedSoft USA
19528 Ventura Blvd. #133
Tarzana, CA 91356
(818) 887-3034
For all Benelux customers (Belgium, Netherlands and Luxembourg):
Horacio Software
Aardappelmarkt 23
NL-3311 BA Dordrecht
Nederland
Tel/Fax : +31 ( 78) 147059
Compuserve : 72072,30
For all other European customers:
SpeedSoft GbR Nrnberger & Partner
c/o Rene Nrnberger
Arthur-Strobel-Str. 12
09127 Chemnitz
FAX : +49 (371) 2176173
Compuserve: 100614,306
Internet: speedsoft@special.infox.com
Support: support@special.infox.com
Beta-Tester: speedpascal.beta@special.infox.com
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Technical information about DB2 for OS/2 on WWW
More than 300 pages of technical information about DB2 for OS/2 (DB2/2)
Version 1 available at WWW from http://www.nta.no/brukere/olea/db2book.
The material is offered as eight PostScript files, and ranges from beginners
tutorial to quite complicated. Areas covered include:
Tables, views, indexes
QM procedures and panels
QM command interface
All aspects of SQL
Programming with REXX, C, C++, and Smalltalk
Logging and recovery
Date and time arithmetic
Intro to set theory and relational algebra
And more...
A lot of the material applies to other DB2/CS products (e.g. DB2/6000). A
significant subset applies to any SQL implementation (DB2/MVS, Informix,
Ingres, Oracle, Rdb, Sybase, etc).
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
RexxBase Has Been Updated to Version 2.02
June 15, 1995
American Coders, Ltd
POB 97462
Raleigh, NC 27624 USA
American Coders, LTD release an update to its shareware program RexxBase.
RexxBase is a REXX API DLL that allows REXX programs to use dBase III and IV
DBF, DBT, NDX and MDX files. This update contains several bug fixes, program
enhancements and documentation changes. The newest release can be found in
the file RXBAS202.ZIP.
The following is a list of the program changes.
Corrected documentation error. RexxBase.SkipDeleted switches use YES or
NO.
Corrected DLL to reflect documentation: RexxBase.dBaseFileType should be
RexxBase.dBaseFileFormat. Use RexxBase.dBaseFileFormat.
Corrected DLL to reflect documentation: RexxBase.dBaseFileType default
value is "dbase3".
Improved GotoRecord function. Specifically TOP parameter and indexes now
in synch.
CREATE and PACKING functions failed for dBase IV memo fields.
Corrected documentation error. References to
RexxBase.AllowDuplicateIndex corrected to RexxBase.AllowDuplicateIndexes.
Corrected Reindex problem. Not building control blocks correctly.
Function required closing DBF before using again.
Patched Reindex function memory leak.
CreateDBFFrom function required closing source DBF before using again.
Restored CloseAllDBF to unregistered version.
Filter routines recalculated dates twice to produce incorrect
results(rv).
REXXBASE.EXE concatenated INDEX filenames incorrectly.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
OS/2 USERS GROUP MEETINGS
[Editor's note - EDM/2 does not normally publish dates of SIG meetings, but
these dates were posted well enough in advance and contain topics that deal
with application development, so we made an exception by eliminating the non-
relevant dates.]
New York, NY
Jul 17 Presentation Manager and Kernel API overview
Aug 21 Intro to REXX + REXX and the Workplace Shell
Sep 18 Debugging with IPMD
Oct 16 C++ User Interface Class Library
All meetings will be held at the offices of the IBM Corporation 590 Madison
Avenue in New York City, starting at 6 PM.
All are welcome.
Call the NYPC Voice BBS at 212-533-NYPC and enter menu code OST for last
minute changes. For other information call Bill Zack at 203-255-2979.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Safetynet's StopLight is Now Available
Safetynet, Inc. has made available for Internet downloading its StopLight for
OS/2 security software. StopLight for OS/2 goes far beyond Workplace Shell
protection, and provides:
file and directory-level security (Read, Write, Create, Delete, Execute)
for all OS/2 modes including PM, command prompt (OS/2 and DOS), dual
boot, and Win-OS/2
OS/2 2.x and OS/2 Warp compatibility
unlimited users per workstation
administrator and user security levels
audit trail
hard disk lock prevents booting from diskette to access the hard disk
data encryption (USA version only)
keyboard lock
dual boot security for identical security when booting into DOS or OS/2
much more...
The full product (without hard disk lock) is available for evaluation from our
WWW and FTP sites. If you need more information, please call our tech support
department at 1- 800-OS2-SAFE or send e-mail to support@safe.net.
http://www.safe.net/safety/
ftp://ftp.safe.net/pub/safetynet/
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
EDM/2 Now Distributed to BBS's in Denmark
EDM/2 announces the addition of Jesper Nielsen as a new network distributor.
Jesper's responsibility is in the distribution of EDM/2 to various bulletin
boards in Denmark. Send email to afdata@pop02.ny.us.ibm.net for more
information.
ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
Comprehensive OS/2 TCP/IP application homepage
The TCP/IP applications list has been converted to HTML and moved. It is
available at http://wc62.residence.gatech.edu/sorensen/tcpip.html.
This page lists all known shareware/freeware/demoware TCP/IP applications for
OS/2 and is catagorized. It is updated based upon when hobbes.nmsu.edu cleans
its /incoming directory.
Please e-mail any suggestions, additions, changes, etc. to
sorensen@wc62.residence.gatech.edu (or use the mailto: tag on the page). The
author is also on the IRC channel #OS/2 as No_one.
FYI - the text based version is outdated, and the wc51 server should no longer
be considered stable.
ΓòÉΓòÉΓòÉ 5. How Do I Get EDM/2? ΓòÉΓòÉΓòÉ
How Do I Get EDM/2?
EDM/2 can be obtained in any of the following ways:
On the Internet
All back issues are available via anonymous FTP from the following sites:
- hobbes.nmsu.edu in the /os2/newsltr directory.
- ftp.luth.se in the /pub/os2/programming/newsletter directory.
- generalhq.pc.cc.cmu.edu in the /pub/newsletters/edm2 directory.
The EDM/2 mailing list. Send an empty message to edm2-info@knex.mind.org
to receive a file containing (among other things) instructions for
subscribing to EDM/2. This is a UUCP connection, so be patient please.
IBM's external gopher/WWW server in Almaden. The address is
index.almaden.ibm.com and it is in the "Non-IBM-Originated" submenu of
the "OS/2 Information" menu; the URL is
"gopher://index.almaden.ibm.com/1nonibm/os2nonib.70".
On Compuserve
All back issues are available in the OS/2 Developers Forum 2.
IBM Internal
IBM's internal gopher/WWW server in Almaden. The address is
n6tfx.almaden.ibm.com and it is in the "Non-IBM-Originated Files" menu;
the URL is "gopher://n6tfx.almaden.ibm.com/1!!nonibm/nonibm.70".
On BBS's
From BBS's in Denmark, send email to Jesper Nielsen at
afdata@pop02.ny.us.ibm.net for a location near you.
How do I Get EDM/2? - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6. C++ Compiler Review (Part 1) ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
C++ Compiler Review (Part 1)
Written by Gordon Zeglinski
Introduction
This issue kicks off our look at the various C/C++ compilers for OS/2. We will
look at VisualAge C++, Watcom C/C++ 10a, Metaware High C/C++ 3.32 and hopefully
Borland C++ 2.0. We start by giving an overview of the development environment
and the features of each compiler. After we look at what each compiler has to
offer, we will compare the executables generated by each compiler (size and
speed) as well as the compile times for each compiler. These tests will consist
of compiling various OS/2 utilities (like unzip, zip, POVRay, sysbench, etc.),
a C++ test program, a Standardized Template Library (STL) example, and the
source code to AdeptXBBS.
In this issue, we will look at Watcom C/C++ version 10 and IBM's Visual Age C++
(C-Set++ 3.0).
Before we start, I'll state my own compiler background. For the last 2 years,
I have been using C-Set++ 2.x to develop OS/2 code. I've become very familiar
with this environment, and invariably I will use it as the base to which I
formulate qualitative statements. A review of C-Set++ 2.1 appeared in volume
1, issue 5 of EDM/2.
All the compilers will be run on a 486 DX2/66 MHz PC clone with 20M of RAM
running Warp Fullpack.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.2. Visual Age C++ for OS/2 version 3.0 ΓòÉΓòÉΓòÉ
Visual Age C++ for OS/2 version 3.0
A full install of Visual Age C++ (VAC++) requires about 180M of disk space. It
generates only 32-bit OS/2 programs. This package is the successor to C-Set++
version 2.1. Thus, comparing it to C-Set++ 2.1 is natural.
VAC++ has many new features over C-Set++ 2.1. Officially they include:
Performance improvements in the compiler and linker
Direct to SOM (DTS) support in the compiler
New Class Browser
Live Parsing Editor
The Visual Builder - an object oriented graphical program code generator
"Open Class Library" - allows C++ applications to be portable to multiple
platforms (Unix, Power PC, Windows 32-bit, etc.) when VisualAge becomes
available for these platforms
Database access classes
Multimedia classes
Workframe 3.0
Installation over C-Set++ 2.1 was somewhat of a pain. The old copy of C-Set++
must be completely deleted and all references to it have to be removed from
CONFIG.SYS. The install uses the standard CID used by many new IBM products.
Other than manually having to clean up the old install, it's a fairly simple
installation. The Warp toolkit, workframe, compiler and related tools are all
installed at the same time. Once you setup the install, it will successfully
complete unattended. Considering it takes about 30 minutes to install off a
double speed CD drive, it's great being able to leave the machine alone and go
do something useful. One problem with the Warp toolkit is that it messes up
the environment variables need by the SOM Developer's Toolkit (if you have
this toolkit installed). Some manual tweaking will be necessary to get the
SOM toolkit working properly again.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.3. Compiler ΓòÉΓòÉΓòÉ
Compiler
As in C-Set++ 2.1, the compiler needs a fair bit of RAM and is primarily disk
bound on this system. The compiler is about 1.3 times slower compiling a large
C based project than C-Set++ 2.1. Also the compiler seems to be more RAM
hungry as well. However, the compiler is noticeably faster during the linking
of C++ code that uses templates. In addition to the DTS support, the C runtime
library now has new functions that improve heap maintenance. In addition to
multiple heaps, heap checking functions are now supported. POSIX locale's and
support functions have been added as well.
I've run into several optimizer bugs while testing the compiler. Fortunately,
these bugs have been fixed in the compiler CSD that was recently released.
This CSD seems to reduce the compiler's memory consumption slightly as well. I
still have one outstanding bug report with technical support: calling
PrfOpenProfile() causing an access violation exception. Migrating existing
applications to VAC++ may require a bit of work. If you are packaging your own
copy of the C runtime library, you will need to redo the DEF file that controls
which functions you are exporting. As well, the names of several libraries
have changed. If you are explicitly linking to any of these libraries, you
will have to change their names in your makefiles.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.4. Development Environment ΓòÉΓòÉΓòÉ
Development Environment
The Workframe/2 product has always been a flexible and easily extended
programming environment. Version 3.0 is completely different than version 2.1.
It combines some some of the concepts of both Workframe 1.0 and 2.1 into a new
easy to understand package. However, if you had used version 2.1, you will be
scratching your head for a while as you relearn how to do things. (It will be
a long while, too.)
Something weird is going on with the Workframe, too; everyone I've talked to
outside of IBM has significant performance problems. For instance, pop-up
menus take seconds to appear, and anything involving filling in the project's
filenames takes almost half a minute to finish. During this time, the CPU
usage goes way up and the system becomes sluggish. One person inside IBM, who
is extremely knowledgeable about the inner's of the Workframe, has reported
performance levels that are FAR better than what I've seen.
In addition to the performance problem, MAKEMAKE doesn't always generate
makefiles that work. I tried to migrate my WF version 2.1 projects to version
3.0, but the process took too long and was awkward. It was faster creating new
3.0 projects from scratch.
So, let's start by forgetting all we know about WF 2.1 and throwing away all
our previous projects. How hard is it to get a project working? Unlike
version 2.1, version 3.0 comes properly configured. To start a new project,
you drag out and drop a copy of the project template. Then, you open its
settings to configure the working directory, target, and the various build
parameters. There are several great new features that should significantly
reduce the amount of time it takes to configure a new project or toggle a
project from "development mode" to "distribution mode". In version 2.1 one had
to have multiple projects one for each mode. This made it extremely awkward to
toggle a project's mode. "Build Smarts" in version 3.0 makes this easy.
Overall, version 3.0 is more stable and easy to start using than version 2.1.
However, the performance problems and the faulty MAKEMAKE result in version 3.0
being less useful than version 2.1.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.5. Debugger ΓòÉΓòÉΓòÉ
Debugger
IPMD version 2.x (the debugger in C-Set++ 2.x) had been the OS/2 debugger to
beat. It has many features to aid in debugging PM and multi-threaded programs
effectively. Version 3.0 adds to this feature list but removes the "hierarchy
browser". (I always wondered why they put a C++ hierarchy browser in the
debugger in the first place. It merely duplicates some of the functionality in
the browser.) A quick summary of the new features include:
child process debugging - allows processes started by the debugged
program to be debugged.
exception filtering - allows the debugger to be configured to ignore
certain exceptions
SOM support - allows SOM classes to be monitored in the monitor windows.
Check heap when stopping - the debugger checks the heap when the program
stops executing (ie. at a breakpoint or after a step command)
improved call stack now displays more information about the stack usage
The heap check function is particularly useful when searching for memory
corruption. The strange thing, though, is that there isn't a way to check the
heap at any time. The heap can only be automatically checked when the
debugged program has been stopped by the debugger. The PM Message Spy and
Window Analysis functions are still present and have been redesigned to
improve functionality.
Overall, the debugger's feature set has been greatly improved. However, it
has numerous bugs which make it less useful than the previous version.
Following is a brief list of problems I've encountered while moving 3
medium-to-large programs to VAC++:
in asynchronous debug mode, the debugger "looses control" of the PM
program. It's as if the debugger can't terminate the debugged program.
Trying to "restart" the application results in the application being run
until the user terminates the application. Once terminated, the debugger
"restarts" the application.
in syncronous mode, trying to step into (pressing "I") a function will
result in the debugger hanging.
after an access violation exception occurs in an OS/2 DLL, doing anything
other than continuing to execute the program can result in the debugger
soft hanging the system.
in syncronous mode, doing a lot of stepping over (pressing "O") can
result in hanging the debugger.
occasionally, when hitting a break point in thread 10 or 11 of the
program, the debugger crashes with an access violation in one of its
DLLs.
Note: all of these bugs are reproducible in all 3 of the ported applications
while debugging multithreaded C or C++ PM code.
Because stepping into or over functions is a fundamental feature of a debugger
and the severity of the other bugs I found, I have to say that the debugger is
presently useless for PM programs. I don't have any large text mode programs
to test the debugger on so it may very well work fine for these types of
applications.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.6. Browser ΓòÉΓòÉΓòÉ
Browser
The browser now has support for SOM classes and has a new interface. When
running at 1280x1024, it would crash if I tried to open a graphical view.
Reducing the resolution to 800x600 (used for the screen shots) allowed the
graphical view to work. A nice feature is that the file menu has options to
load in the browser information for classes in the Open Class library; this
makes the browser a good way to see how third party libraries are designed.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.7. Profiler ΓòÉΓòÉΓòÉ
Profiler
The profiler in version 2.1 was an excellent tool for gathering information on
how your program runs. To profile the program it has to be compiled with
profiling hooks inserted into the generated code by the compiler. The hooks
are used to inform the profiler when a function is called. The result is that
a highly accurate map of program execution can be generated, which can then be
viewed in a multitude of ways to show time-based or calling-chain information.
The major improvements to version 3.0 are support to trace up to 64 threads,
trace runtime-loaded DLLs, and the ability to start and stop tracing any time
during an applications execution. The only problem with version 3.0 is that it
crashes on startup.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.8. Visual Builder ΓòÉΓòÉΓòÉ
Visual Builder
The visual builder is written in Smalltalk and it needs a lot of memory. Most
people I talk to say to run the builder well, you need 32M of RAM. I gave it a
try on this system the HD was trashing a fair bit and the builder was sluggish,
but it looked nice. Its design is very object-oriented and fairly easy to pick
up. If it only would use less memory...
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.9. Open Class Library ΓòÉΓòÉΓòÉ
Open Class Library
The Open Class Library is designed to allow one's C++ code to be easily moved
from one platform to another. There is a price to pay for portability, though.
The library is quite large and needs a fair bit of memory at runtime. For
small projects, it may be better to simply write the code to the raw API. The
class supports various objects to manipulate the user-interface, collection
classes, and I/O streams. The most notable improvements to the user interface
support is the inclusion of toolbar support, 2-D graphics, animated buttons and
flyover help. Flyover help is textual information that appears by the mouse
when the mouse is positioned over a button or toolbar element.
Note: a CSD for this component is available.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.10. Documentation ΓòÉΓòÉΓòÉ
Documentation
As usual, the amount of paper documents is kept to a minimum. All
documentation is on-line in either INF or BOO format. The INF documents have
been refined over C-Set++ 2.1 in that they are now easier to use and search.
For the paper junky, Postscript files are included.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.11. Summary ΓòÉΓòÉΓòÉ
Summary
Within days of getting VAC++, a CSD for the compiler and Open Class library
were available. The compiler CSD lists the optimization bug I found while
compiling unzip as fixed, but it did not fix the problem I have while calling
PrfOpenProfile(). As a whole, this package has many excellent features, many
of which should make code development much easier and faster. Unfortunately,
it presently has too many bugs to act as a replacement for large projects
developed under C-Set++ 2.1.
Given the C-Set++ team's track record with providing fixes for C-Set++ 2.1,
though, I think that once we get a round of CSDs for all the components, this
will be the compiler package for OS/2. It's likely that by the time a new
project grows to the stage where the bugs I have found are important, there
will be CSDs out to fix them.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.12. WATCOM C/C++ 10a ΓòÉΓòÉΓòÉ
WATCOM C/C++ 10a
Watcom C/C++ 10a requires about 180M of disk space for a full installation.
This includes support for:
16-bit development for the following platforms:
- OS/2 1.x
- DOS
- Windows 3.x applications
32-bit development for the following platforms:
- 32-bit OS/2 2.x
- extended DOS
- Windows NT
- Win32s
- Win 3.x using a proprietary windows extender
- Novell NLMs
- Autocad ADS applications
[Editor's note - I believe it also supports QNX development.]
The package includes a multi-platform GUI and text mode debugger, a class
browser, a profiler, a GUI and text mode editor, a windows resource editor,
OS/2 2.1 toolkit, SOM 2.0 developers toolkit, and Microsoft's foundation
classes for Windows. (Yes, the Windows development tools are richer than the
tools for OS/2 PM development.) There are no message "spy" utilities, window
hierarchy utilities, etc. for PM development. IBM's Developers Connection
CD's include basic applications that allow the developer to spy on messages,
etc. Having PM-related debugging features integrated into the debugger is
advantageous when developing PM apps, though. Also, the OS/2 version of the
text editor isn't PM based. The biggest letdown with the package is that
there are more Windows utilities than OS/2 ones. The main components of the
package, however, have native OS/2 support.
A complaint that I have is that the installation program needs to be polished.
While it is capable of copying the most of files to the HD, it only partially
configures the system. It doesn't set the INCLUDE or LIB paths at all,
configure the DOS AUTOEXEC.BAT, or setup the Windows environments (when
installing Windows cross platform support). Also, when running Warp you have
to edit the CONFIG.SYS after installing Watcom but before rebooting. You must
move the ...\WATCOM\BINP\DLL;...\WATCOM\SOM\LIB to the end of your LIBPATH
otherwise the WPS will hang when you reboot due to a SOM version difference.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.13. Compiler ΓòÉΓòÉΓòÉ
Compiler
The compiler is lean and mean. Compile speed has been greatly improved over
that of Watcom C/C++ 9.5. In fact this compiler is now considerably faster
than C-Set++ 2.1. As with version 9.5, the compiler is easy on your HD because
it is primarily CPU bound. Thus, a faster CPU will have a dramatic effect on
compilation time.
The part I like the most about the compiler is its cross-platform capabilities.
The 32-bit OS/2 compiler can generate code for any 32-bit target platform.
Similarly, the 16-bit compiler can generate code for any 16-bit target
platform. In fact, I used the 16-bit OS/2 compiler to create a Windows 3.x
16-bit applications. (If you have to write Windows programs you might as well
use an OS/2 native development environment!) Another bonus is that the package
ships with an assembler. Combining the 16-bit C/C++ compiler with the
assembler, you have a great OS/2 device driver development environment. (It
beats MSC 6.0 + MASM any day, in my opinion.)
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.14. Development Environment ΓòÉΓòÉΓòÉ
Development Environment
The IDE is somewhat similar to the Borland C++ IDE - it's easy to use and
fairly intuitive. Several targets can be grouped into a single project.
However, the configuring the IDE is not straightforward. I couldn't find any
menus or documentation on how to add support for different tools into the IDE.
By default, the IDE expects all C and C++ files to use the suffixes .C and .CPP
respectively. This is annoying if you want to distinguish between the "type"
of C code. An interesting feature, though, is that you can assign specific
compiler switches to individual files. Typically, IDE's only allow you to
configure a set of swtiches for a given file type. All .C files must then use
the same switches. This is not the case for the Watcom IDE.
My biggest complaints about the IDE are that it can crash when you least want
it to (usually right after making a lot of changes to the project), it uses EPM
as its editor, and it needs a bit more polish. Once it's polished up a bit and
configuration is made easier it should be great.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.15. Debugger ΓòÉΓòÉΓòÉ
Debugger
The debugger has both a PM and text mode version. The PM version, though, is
essentially the text mode debugger in PM version. It lacks any PM-specific
features and is rather plain. A useful feature is that it can execute macros
when a breakpoint is encountered. Its biggest feature is that the OS/2 native
debugger can be used to "remote" debug DOS and Windows programs. This "remote"
debugging can be performed on a networked machine or on the local machine.
Unfortunately this feature doesn't work completely under Warp.
Also, debugging multi-threaded programs under Warp needs a special command line
switch (see http://www.watcom.on.ca for info). These problems are supposed to
be fixed in version 10.5, though. The debug information can be stored in SYM
files, giving you the advantage of not having to rebuild the executable to make
a distributable form of your code.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.16. Browser ΓòÉΓòÉΓòÉ
Browser
The browser lets you view inheritance information and the relationship between
functions in a source file. The biggest problem with the browser is that it
includes all the structures and classes. This can make it quite hard to find
the class you are interested in, if you include <os2.h> or <windows.h>. While
you can selectively remove objects from the inheritance view, there is no way
to remove or include all objects using criteria such as where they are defined,
how they are defined, etc. The result is that one often has to remove all the
objects from the inheritance view and then add back those that one is
interested in. An editor can be launched from the browser to modify the source
code. (Note: the IDE crashed while launching the editor, but I have not been
able to reproduce this.)
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.17. Profiler ΓòÉΓòÉΓòÉ
Profiler
The profiler displays the data gathered by the sampler. Unfortunately the
sampler didn't work properly under Warp. While trying to sample a
multi-threaded PM application, the sampler would report an internal error when
the sampled program terminated.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.18. Documentation ΓòÉΓòÉΓòÉ
Documentation
The basic package includes compiler and tools on CD along with a getting
started book. The documentation package is extra. It includes the following:
Watcom Graphical Tools User's Guide
Watcom Tools User Guide
Watcom C++ Class Library Reference
Watcom C/C++ User's Guide
Watcom C Library Reference
Watcom Linker User's Guide
Watcom Programmer's Guide
Watcom Debugger User's Guide
Watcom C Language Reference *
The C++ Programming Language, second Edition by Bjarne Stroustrup (see
note below).
Note: Bjarne Stroustrup's book is not found in the online OS/2 documentation,
of course.
The book The C++ Programming Language is an excellent reference and is not
specific to the Watcom compiler. The rest of the books are rather hard to
follow, though. It's sometimes hard to find the information that deals with
the particular host and target environment you are using. I suppose this is
the price one pays when the package supports so many target environments.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.19. Summary ΓòÉΓòÉΓòÉ
Summary
The Watcom package allows one to make applications 16 and 32-bit applications
for OS/2, DOS and Windows (NT, et al.) all from an OS/2-based environment. The
compiler generates very tight, fast code and does this relatively fast. The
incompatibilities it has with Warp should be taken care of in version 10.5. In
particular, this package - when combined with OS/2 - makes an excellent DOS and
Windows development environment. Its biggest weakness is the lack of any PM
specific functions in its debugger, and its Warp incompatibilities.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 6.20. Wrapping Things Up ΓòÉΓòÉΓòÉ
Wrapping Things Up
In this issue, we looked at Watcom C/C++ 10a and Visual Age C++ version 3.0.
Watcom C/C++ 10.0 was written before the release of Warp. While its debugger
and profiler have problems running under Warp, a new version of Watcom C/C++
has just been released which I am told is Warp-friendly. Watcom C/C++ makes a
good multi-platform compiler although it would be even better if it included
some multi-platform GUI objects.
Visual Age C++ comes with a class library designed for cross platform usage and
a nice visual builder that utilizes this class library. The biggest problem
with Visual Age C++ is that currently it is has too many bugs in its tools to
be useful for handling large applications where a debugger and profiler may be
needed.
In the next issue we will look at the Metaware High C/C++ compiler and possibly
Borland C/C++ for OS/2. We will also see how well each compiler generates
various C and C++ code, and test their C++ features.
C++ Compiler Review (Part 1) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7. Gearing Up For Games (Part 2) ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
Gearing Up For Games (Part 2)
Written by Michael T. Duffy
Introduction
Welcome back to Gearing Up For Games. Last time we looked into how to use DIVE
to blit images to the screen, and then developed a canvas class to make
accessing the DIVE buffer easier. This time we will look at how palettes are
handled under OS/2, and we will look at decoding and displaying the common
bitmap format of PCX to our canvas object. This article builds on the previous
one, so the canvas class and DIVE code from the last article will be used in
this (and future) articles. Eventually all this code will go together to
create a simple game, and the concepts will allow you to branch out and write
more meaty games that run natively under OS/2. So without further ado...
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.2. Palettes ΓòÉΓòÉΓòÉ
Palettes
Before I start my discussion of palettes, I must call attention to an article
written for EDM/2 way back in issue 1-1. Raja Thiagarajan wrote an unofficial
guide to the palette manager, and I think it may have even been Raja who
introduced me to EDM/2 in the first place (Thanks!). I would suggest that you
read his article in addition to this one, because it covers some aspects of the
palette manager which I will not touch on.
I would also like to thank the many people on the Internet who helped me out
when I was first learning about palettes. Palettes under OS/2 drove me crazy
for several months before I could finally control them to the point that they
did what I wanted them to do. Even now they occasionally surprise me; in
preparing for this article I discovered that some of the palette code I had
been using for a long time would only display a black window in 256 color mode,
whereas it worked fine in the 32k color mode I normally use! Just when I think
I completely understand palettes, they surprise me with something like this.
With the information in this article, the article in EDM/2 issue 1-1, and the
API specifications in the manuals you should have enough information to
experiment around with palettes. The approach to palettes that I present here
seems to work best for games that use DIVE, though there may be some subtle
palette tricks that I am unaware of and thus don't cover. Palettes are tricky
to use though, so be certain to approach any experimentation with lots of
patience, otherwise you may well be driven insane.
One final note before we begin: This article makes the assumption that our
application will display a 256 color image in our application's window, and use
the DIVE API to do it. DIVE is capable of displaying images with more than 256
colors, but for simplicity's sake this series of articles will not cover those
situations.
What is a Palette?
A palette is an array that tells PM what colors to use when displaying an
image. A 256 color bitmapped image has one byte for each pixel. This byte
tells what color in which to display that pixel. A palette is used to convert
that byte into the color information the display hardware needs to actually put
the color on the monitor. Palettes can have up to 256 entries. Each entry
describes one color, and the color information is stored in three bytes, one
each for the component colors red, blue, and green. As they are stored in
bytes, each of these component colors can have a value ranging from 0 to 255.
Using varying amounts of these three colors, any other color can be described.
A bright red would have Red set to 255 and both Green and Blue set to zero.
Black is achieved when all three are set to zero and white results from all
three being set to 255.
All palette activities for an OS/2 program are handled through the palette
manager. The palette manager is part of the OS/2 API, and is accessed through
the API function calls. A palette manager is needed in a GUI environment
because multiple programs may be running at the same time and each program may
require different color needs. The palette manager tries it's best to meet
these needs.
However, the palette manager is restricted by hardware limitations. Many
common color modes of video cards have a maximum of being able to display 256
colors at the same time. Although each of these colors may be selected from
among 262,144 colors (256k colors), on the graphics card there is a physical
maximum of 256 color registers to hold the colors. This has led to the
development of two different kinds of palettes: physical and logical.
The physical palette is the palette set in these hardware registers. Under
OS/2, you can not set the physical palette directly. The palette manager will
always determine what colors go in the physical palette, and in what indices
these colors are placed. You can read the physical palette with
GpiQueryRealColors(), but you cannot set it.
[Note: There is one exception to the above. In dive.h a comment explains a
way to set the physical palette with undocumented calls. I would urge everyone
to avoid this method though, since it is unknown what that code would do in a
non-paletted video environment (such as the 32 and 64 bit modes), and this
method may not be supported on different hardware (such as the PowerPC, or
future Intel based hardware). I have not experimented with the undocumented
code in dive.h because of lack of information on the undocumented calls, and
because I have been able to achieve the results I need through the palette
manager and without messing up the integrity of the desktop.]
Although programs cannot access the physical palettes, they can have their own
logical palettes. A logical palette is set up in the same format as a physical
palette. The logical palette is sent to the palette manager, and whenever your
window has focus, the palette manager will change the physical palette to match
the logical palette as much as possible. For the colors that do not match the
physical palette exactly, the palette manager will decide the closest match,
and use that instead. When you request that color 4 be drawn to the screen,
the palette manager will look at color 4 in the logical palette, decide what
color it most closely matches in the physical palette, and send the new color
out to the display hardware.
By approaching palettes this way, several applications can share the scarce
palette entries at the same time. The palette manager will always try and
fulfill the needs of the palette in the active window. Applications whose
windows are not active will still have their colors remapped to the closest
palette entry, but the palette manager will not use the inactive palettes to
determine the contents of the physical palette. Note that remapping is done
when an image is drawn to the screen, such as with DiveBlitImage(). If the
display is in a 256 color mode, the physical palette changes, and a window is
not redrawn, then its colors will be wrong.
But what about graphics modes with more than 256 colors? Many users of OS/2
have their displays set to modes that offer 32k, 64k, or even 16.4 million
colors. In these cases, there are no color registers to fill. If two
applications request palettes of 256 different colors each, both requests can
be met without any problem. In these cases there is no physical palette to
set, but a logical palette is still required. The system must know what color
each of the 256 palette entries in our source bitmap is to be displayed as when
it converts each pixel to a 15, 16, or 24 bit color value.
How to Use Palettes Under OS/2
Our goal is to use palettes in conjunction with the DIVE API in order to
display images in a window. Although DIVE has the calls DiveSetSourcePalette()
and DiveSetDestinationPalette(), neither of these calls affects the physical
palette in any way. These calls are used to tell DIVE what logical palette it
is mapping from and what physical palette it is mapping to. To change the
physical palette in 256 color video modes, you must request that the palette
manager remap the physical palette as much as possible to a specified logical
palette.
The steps for the creation and activation of a palette are as follows:
1. Query the device context of your client window with WinOpenWindowDC().
2. Create a presentation space from the device context with GpiCreatePS().
You cannot use a cached-micro PS (from WinGetPS()). We will use a micro
PS.
3. Create an array that describes your palette. (The format for this array
is described below.) Use the PC_RESERVED flag to obtain as many of your
colors as possible.
4. Create an OS/2 palette from this array and obtain a handle to the new
palette with GpiCreatePalette().
5. Select the palette into the presentation space with GpiSelectPalette().
6. Make the palette active ("realize it") with WinRealizePalette().
7. Set the palette DIVE will use for your source bitmap by using your
original array with DiveSetSourcePalette().
8. Tell DIVE what the physical palette is by either using
GpiQueryRealColors() and passing the result to
DiveSetDestinationPalette(), or call
DiveSetDestinationPalette(hDive,0,256,0).
9. Blit your image.
During normal processing you have a few tasks to perform to maintain the
palette.
10. On WM_REALIZEPALETTE messages, inform DIVE that the physical palette may
have changed. Do this with either method described in step 8, though
simply calling DiveSetDestinationPalette(hDive,0,256,0) is the easiest.
11. On a WM_ACTIVATE message, if your application is losing focus, free up
your palette so that other applications may have as many of their colors
mapped into the physical palette as possible. Do this by selecting a
null palette into the presentation space with GpiSelectPalette(), and
activate this null palette with WinRealizePalette().
12. On a WM_ACTIVATE message, if your application is gaining focus select and
activate your desired palette again so that the physical palette will be
remapped more closely to your logical one. Use GpiSelectPalette() and
WinRealizePalette() to achieve this.
When you are done using the palette and your game is ready to end.
13. De-select your palette from the presentation space by selecting a null
palette with GpiSelectPalette().
14. Destroy the palette with GpiDeletePalette().
15. Destroy the presentation space with GpiDestroyPS().
Notes
Certain things must be considered in each of the above steps. The important
ones are detailed below, and the general implementation of the steps can be
viewed in the included sample files game2.cpp and os2pal.cpp.
Step 1: WinOpenWindowDC() will only work once per window. Multiple calls will
fail, so be certain to save the returned device context handle.
Step 2: again, make certain that you do not use a cached micro PS. For our
purposes, we will call GpiCreatePS() with the flags PU_PELS, GPIF_DEFAULT,
GPIT_MICRO, and GPIA_ASSOC. Also, be certain to save the handle to this
presentation space and use it throughout your program. This includes using it
with the DIVE code that calls GpiCreateRegion(), GpiQueryRegionRects(), and
GpiDestroyRegion(). If you create and use separate PSs for palette and DIVE
tasks, then in 256 color video modes your blitted images will appear black,
even though they will blit correctly in higher color resolution modes.
Step 3: the array that describes your palette is an array of unsigned longs.
Three of the bytes in the ULONG describe the red, blue, and green components
of the color, and the fourth byte is a flag byte. The flag byte tells the
palette manager a bit more information about that specific color. For our
purposes, we will set all of the flags to the same value. This value is
PC_RESERVED, and it signals the palette manager that the color in question may
change frequently due to palette animation. Therefore the palette manger will
not use these colors for other windows, and you have more control over what
colors are put in the physical palette while your window has focus.
The formula for placing the four component bytes into a ULONG is:
ulArrayEntry = ((ULONG)byFlag << 24) + ((ULONG)byRed << 16) + ((ULONG)byGreen << 8) + byBlue;
[Editor's note - you can also use the RGB2 structure for this purpose.]
Step 4: with GpiCreatePalette(), for flOptions we use LCOL_PURECOLOR to
prevent dithering, but we do not use LCOL_OVERRIDE_DEFAULT_COLORS in order to
keep from messing up the desktop colors. For ulFormat we use LCOLF_CONSECRGB
as it is currently the only supported format. We pass this function an array
of the format described in step 3 above.
Step 5: presentation spaces are used to hold display information for a
window. If we were to use Gpi drawing routines, the PS would hold the current
drawing colors, line characteristics, marker styles, character attributes, and
so on. The PS also holds palette information for our window. To tell the PS
which palette to use, we call GpiSelectPalette().
Step 6: even though we selected a palette to use for our PS in step 5, this
palette is not yet made active. In order to tell the system to use our
palette whenever our window has focus, we must call WinRealizePalette().
Step 7: we must tell DIVE which color each byte in our DIVE buffer stands
for. This is done with DiveSetSourcePalette(). If DiveSetSourcePalette() is
not called, then the default palette is used. If your DIVE buffer does not
use the default palette, your results will be unpredictable.
Step 8: we must also tell DIVE about the colors of the display hardware.
This can be done by retrieving the physical palette with GpiQueryRealColors()
and passing it to DiveSetDestinationPalette(). A shortcut to this is to call
DiveSetDestinationPalette() with a null pointer to the palette array. This
will instruct the routine to call GpiQueryRealColors() on its own. The notes
for this step also apply to step 10 and the WM_REALIZEPALETTE message.
Steps 11 and 12: When our game loses focus, one of the things we want to do
is give the system back as many colors as possible so that other applications
may use them. Since we use the PC_RESERVED flag with all colors of our game's
palettes, our palette holds a lot of weight with the palette manager. By
deactivating our palette when we lose focus, the window receiving focus will
have its colors more readily remapped into the physical palette. By
specifically reactivating our palette when we regain focus, our colors are set
in the physical palette without delay. We need to redraw our window when we
regain focus in case we received focus when another overlapping window closed.
Such situations lead to a corrupted display if we don't redraw our window. In
the future when we have a blit thread continually drawing our image to the
window, the explicit redraw will not be needed.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.3. The OS2Palette object ΓòÉΓòÉΓòÉ
The OS2Palette object
Many of the above steps can be combined because they always occur after one
another, such as GpiSelectPalette() and WinRealizePalette(). Also, we may have
to work with palettes other than OS/2 palettes. An example of this are the
palettes stored in compressed bitmap files. To simplify palette operations we
will use a palette object that hides from us repetitive tasks. For learning
about the specific implementation of any of the tasks provided by the palette
object, I encourage you to look at the source code for the object in
os2pal.cpp.
The following functions are those provided by the OS2Palette object. They do
not cover every single aspect of palettes, but they provide an illustration of
the major points. Also, they provide all the functionality we need for our
simple game.
Default16(): sets the palette to the first 16 colors of a standard VGA
palette. This can be done for initialization and testing purposes. This
function illustrates how to organize and set a default palette.
Convert(): this routine converts the internal palette from one format to
another. The two formats implemented in this code are for plain 8-bit RGB
palettes and OS/2 palettes. The former are what you might find in a compressed
bitmap (we will use them in the PCX codec), and the latter are what you will
pass to OS/2 and DIVE.
InitSystemPalette(): this will convert the internal palette to the OS/2
format, create an OS/2 palette, select it into the supplied presentation space,
and realize it.
UninitSystemPalette(): this will de-select the internal palette from the
presentation space, realize a null palette, and destroy the palette. This
routine is called on cleanup.
SuspendSystemPalette(): this will de-select the palette from the presentation
space and realize a null palette, but it will not destroy the palette. This is
meant to be used on a WM_ACTIVATE message. Call RestoreSystemPalette() to
reactivate the palette.
RestoreSystemPalette(): restores the palette suspended by
SuspendSystemPalette().
SetAsDiveSource() and SetAsDiveDestination(): these routines are used to tell
DIVE about the palette. You will usually have at least two palette objects,
one for the DIVE bitmap and one for the screen. If you choose to always set the
DIVE destination palette with DiveSetDestinationPalette(hDive,0,256,0), then a
palette for the screen is not needed.
LoadActualPalette(): this sets the palette to the physical palette.
SetValuesFromRaw8(): this will set a range of values from an array of 8-bit
RGB values.
PaletteFromBlock(), RequestSaveBlock(), and ReleaseSaveBlock(): these three
functions package or unpackage a palette into a single block of data. These
routines will be used in the future when we look at storing data in a single
library file. Currently they may be used to load and save a palette to disk.
SetFlag() and QueryFlag(): these inline functions are for setting and getting
the value that is copied into the flag position of the colors in an OS/2 format
palette.
QueryPaletteArray(): this returns a pointer to the internal array that
contains the palette. The format of the array depends on the format set with
Convert(). One use of this routine would be to supply palette information to a
bitmap encoding routine. First, Convert() would be used to set an 8-bit
palette. Then this routine would be used to get a pointer to the palette
information to send to the encoding routine.
QueryLastErrorCode(): Returns the code of the last error that occurred. This
error code is specified in errcodes.hpp and the associated message is stored in
game2.msg. This error code can be used with PostError(), a routine found in
errdisp.cpp.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.4. Palettes for Multiple Child Windows ΓòÉΓòÉΓòÉ
Palettes for Multiple Child Windows
Sometimes I am very glad that I don't keep a rocket launcher on hand near my
computer. Recently I'm afraid that I would have had to blow my computer into
tiny, unrecognizable pieces considering how much grief it caused me. After
months of being bothered by the same, nagging palette problem, I finally
discovered a solution.
The problem arises when you have two child windows, both of which are using
DIVE to blit an image to its client area. I ran across this situation while I
was writing editors and other utilities for my own game, though such a
situation could very well arise in a game with multiple windows.
In order to get the same palette to display correctly in both windows,
implement a palette as above in the "How To Use Palettes in OS/2" section. The
various steps will be split amongst the parent and children windows as follows:
1. The HDC and the HPS for the palette should be derived from the parent
window. The palette should be created, selected, realized, and
eventually destroyed from the parent window. The parent window will
handle suspending and restoring the system palette on WM_ACTIVATE calls.
2. An HDC and HPS should also be created for each child window, and these
handles will be used to setup the DIVE blitter among other things. No
palettes will be selected into the child windows' HPS's, however.
3. Each child window should have its own instance of DIVE.
4. Instead of setting the DIVE source and destination palettes in the parent
window, send messages to the child windows and have them perform these
tasks. When you send the message, pass a pointer to the palette array as
one of your parameters. Make sure this array is in the OS/2 palette
format.
5. Do not use the shortcut of DiveSetDestinationPalette(hDive,0,256,0). You
will have to use GpiQueryRealColors(), and then pass a pointer to the
returned palette array to each of the child windows so that they can call
DiveSetDestinationPalette() with this info. When you need to update the
destination palette, only call GpiQueryRealColors() once and pass the
same array to both child windows. Every time the parent window receives
a WM_REALIZEPALETTE message, it must query the real palette and pass the
array to each of the child windows. The child windows should not process
the WM_REALIZEPALETTE message.
Performing the above steps should allow the same palette to be used for two
separate child windows.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.5. Graphics Formats ΓòÉΓòÉΓòÉ
Graphics Formats
When graphics are stored to disk, they are usually saved in a special format
rather than just dumping memory to a disk file. These formats contain
additional information about the graphic such as its size, number of colors,
palettes, and other types of info. The graphic data is also usually compressed
in order to save disk space. Compression/decompression algorithms are usually
called codec's, and each graphic format usually has it's own codec which is
different from the others. Codecs differ in their compression ratio, speed,
and quality. Certain codecs throw out some of the original information during
compression, and then try and guess what is missing when they decompress the
image. These are called lossy codecs because they lose some of the data. JPEG
is an example of a format with a lossy codec. Lossless codecs generate the
same image upon decompression as was given to them for compression. Popular
formats with lossless codecs include GIF, PCX, TIF, and PNG.
Our code will deal with PCX files. PCX files have the advantage of being
supported natively by many paint programs both shareware and commercial. This
format was originally developed by ZSoft for their paint program PC Paintbrush,
but it was adopted by many other programs as well due to its ease of use. PCX
files support monochrome, 16-color, and 256 color images though we will only
concern ourselves with the monochrome and 256 color capabilities. PCX files
are also good because their compression scheme is very simple to understand.
It is not a compression scheme that works well for all graphics though, and
many scanned images would wind up larger than where they started if the PCX
scheme were used on them. Nevertheless, it will suit our needs nicely.
As far as implementation in our sample code is concerned, the PCX
encoding/decoding object is derived from a parent class called BitmapPainter.
This allows us to treat different graphic formats in the same way. The same
calls are used to setup, compress, and decompress graphics no matter what
format in which they are stored. Although we will only implement code to deal
with PCX files, you could write code to support other formats without having to
change much code in programs that already use BitmapPainter-derived objects.
Also, our PCX display code will use the Canvas class to hold the decompressed
image. The Canvas class was covered in the first article of this series.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.6. On to PCX! ΓòÉΓòÉΓòÉ
On to PCX!
PCX files have three parts: the header, the image data, and the palette.
Monochrome images only have a header and the image data, since all pixels are
either black or white.
The Header
The header of the PCX looks like this:
typedef struct {
BYTE byManufacturer; // always 0x0a
BYTE byVersion; // version number
BYTE byEncoding; // always 1
BYTE byBitsPerPixel; // color bit depth
USHORT usXmin; // coordinate of left side of image
USHORT usYmin; // coordinate of top of image
USHORT usXmax; // coordinate of right side of image
USHORT usYmax; // coordinate of bottom of image
USHORT usHres; // horizontal resolution of creation device
USHORT usVres; // vertical resolution of creation device
BYTE abyPalette [48]; // color palette for 16 color images
BYTE byReserved;
BYTE byColorPlanes; // number of color planes in the image
USHORT usBytesPerLine; // line buffer size
USHORT usPaletteType; // gray or color palette
BYTE abyFiller [58];
} PCXHEADER;
The header is exactly 128 bytes long, and is always located at the very
beginning of a PCX file. A more detailed meaning of each field is as follows:
Manufacturer: always 0x0a. Checking this byte is the only way to really tell
whether or not a file is a PCX file.
Version: this variable is meant to tell what version of PC Paintbrush created
the file. A zero indicated PC Paintbrush version 2.5. A two or three
signifies version 2.8. A two means that the abyPalette field contains palette
information whereas a three means that the image is either monochrome or meant
to be displayed with the default palette of the device. A five indicates that
the PCX came from version 3.0 or better, and this is the only version that can
support 256 color images.
Encoding: this is always 1, though the field was put here in case ZSoft wanted
to add a different kind of codec to the PCX specification. A 1 signifies that
the image uses a Run- Length Encoding (RLE) codec.
BitsPerPixel: this tells how many bits are used to make a single pixel in a
single color plane. Monochrome images only have black and white pixels, so
they have 1 bit per pixel. 256 color images have 8 bits per pixel since they
need entries from 0 to 255. 16 color images need 4 bits to generate a number
between 0 and 15. However, 16 color images are stored in four color planes, so
they only have one bit per pixel in each color plane. Monochrome and 256 color
images only have a single color plane, so their bits per pixel value is a count
of their total bits. Color planes are explained below.
Xmin, Ymin, Xmax, and Ymax: these values give the boundaries of the image.
Usually Xmin and Ymin will be equal to zero. These coordinates represent the
origin, and the origin is located in the top left hand corner of the image.
Xmax and Ymax give the right and bottom edges respectively. These coordinates
are inclusive. This means that if Xmin is 0 and Xmax is 639, a row of this
image runs from pixel 0 to pixel 639 inclusive. It has a width of 640 pixels.
Therefore when computing the width or the height from these values, be certain
to add 1 to get the correct answer: (i.e. usWidth = usXmax - usXmin + 1).
Hres and Vres: these values give the dimensions of the hardware that generated
the image, and are basically useless values.
Palette: this array of bytes contains a palette for 16 color images. PCX
palette have a red, blue, and green byte for each color, so 3 color bytes times
16 colors leads to the 48 byte length of this array. The PCX format was
developed before 256 color images were available on the PC. As a result, the
designers of the PCX format did not leave room for a 256 color palette. To
solve this problem, the palette for 256 color images was tacked onto the end of
the PCX file, and this array was not used. Since we will not be using 16 color
images, we will ignore this field.
ColorPlanes: this tells how many color planes are used for the image. Color
planes are used because of the way hardware is setup in EGA and VGA cards for
the 4 and 16 color modes. A pixel in these modes has one bit in each bit plane
instead of having its bits side by side as in 256 color mode. The bits in each
of the bit planes are combined to get the color index of a single pixel. If
you haven't encountered bit planes before and don't understand how they are set
up, I would suggest looking in a book on EGA/VGA cards. They take a little bit
of time and space to explain clearly, and since we are not dealing with 16
color formats I will not cover them here.
BytesPerLine: this field tells how many bytes are in a single decompressed
row. This is useful in monochrome and 16 color images, but the bytes per line
in a 256 color image is the same as its width.
PaletteType: this simply tells whether or not an image is meant to be
displayed in color or gray scale. A value of 1 indicates gray scale and a
value of 2 indicates color.
The Codec
The algorithm for decoding a PCX image is simple. You take the current byte of
the image data and look at it's top two bits. If they are both clear, then you
write that byte out to your canvas. If they are both set, you clear them and
that byte becomes your duplication count, or run length. Take the next byte
and copy it to the canvas "run length" number of times. Repeat the process
until you have enough bytes to fill a row. Move to the next row down and
repeat the process for that row. Do this until there are no more rows left in
the image.
The only catch to the above algorithm is when you run across a single pixel
that has information in one or both of the top two bits. Bytes for these types
of pixels are handled as having a run length of 1, since the entire 8 bits of
the byte can be stored in the byte following the run length byte.
Encoding a PCX is just the reverse of this process. Start at the first pixel
in the top row of your image. Count how many times this pixel color appears in
a run. Do not let this run length go over 63, because you can only store the
run length in 6 bits (the top two will be set). If the run of bytes is greater
than one, set the top two bits of the run length and send it to your encode
buffer. Next send the byte to duplicate. If there is only one byte, check and
see if any of the top two bits are set. If one or both are set, output a run
length of one, and then output the byte. Otherwise, simply output the byte.
Repeat until you are done with a row, and then move to the next row down.
Continue in this way until all rows are done.
This same codec is used in both monochrome and 256 color images, though the
pixels are stored slightly differently. For monochrome images, each byte
contains 8 pixels, since only one bit is needed for each pixel. If the bit is
set, it denotes a white pixel. If it is clear, it denotes a black pixel. The
most significant bit is the left most pixel in that byte, and the least
significant pixel is to the right. Bits can be tested in the byte with a
bitwise "and" operation.
256 color images have their bits stored right next to each other. Since it
takes 8 bits per pixel, the entire byte is used for the color index. You can
decode the row directly onto the surface of a Canvas.
The Palette
In monochrome images, there is no palette because the pixels can either be
white or black. In 256 color images, the palette is attached to the end of the
PCX file. The palette is stored as one byte each for the red, green, and blue
components of each color, in that order (RGB). There are 256 colors possible,
so the palette is 3 color bytes * 256 indexes = 768 bytes long. To make sure
that you aren't reading image data instead of palette data, PCX files have the
byte 0x0c right before the palette information starts.
To read a PCX palette you find the end of the file and move back 769 bytes.
Check that byte to see if it equals 0x0c. If it does, read the next 768 bytes
as your palette.
Byte Order
One last note about palettes: To use the palette attached to the PCX file, you
will need to convert it to an OS/2 palette. An OS/2 palette has the elements
Flag-Red-Green-Blue stored in a ULONG. However, Intel based PCs store USHORTs
and ULONGs in a byte reversed order, and if you access the OS/2 palette as an
array of bytes instead of an array of ULONGs, then you must take this into
consideration.
The byte reversal scheme works like this: Suppose you have a variable at
memory location 0x1000. A byte would be stored at location 0x1000, a USHORT
would be in locations 0x1000 and 0x1001, and a ULONG would be stored in
locations 0x1000 through 0x1003. Placing a byte is no problem; just put it in
location 0x1000. A USHORT is made up of two bytes. One byte handles the
lowest 8 bits, and the other byte handles the highest 8-bits. When an Intel
based PC stores the USHORT in memory, it will place the lowest 8 bits in the
first byte (0x1000), and the highest 8 bytes in the next byte (0x1001).
A number under 256, say the value 42, would be stored in the lowest 8 bits of
the USHORT. A pointer to our USHORT would have the value of 0x1000. When the
USHORT is accessed with the pointer, then the bytes will be placed in their
correct order so that the value of 42 is retrieved. However, what if we
typecast this pointer and use it as a pointer to type BYTE. A BYTE can hold
the value of 42, but it is only looking for a single byte in memory (8-bits).
Since the bytes are reversed and the lowest byte is at location 0x1000, the
byte pointer can read the value fine. If the bytes were not reversed, then the
value at 0x1000 would hold a zero and the byte pointer would receive the wrong
value. This is the rationale behind the reversed byte order scheme.
For this same reason, the bytes that make up a ULONG are reversed twice. You
can look at ULONGs like two USHORTs, but the USHORTs are reversed so that the
lowest 8 bits of the ULONG are placed at the first memory location (0x1000).
What all this means for palettes is this: You access the bytes in a PCX one
after another in the order of Red, Green, Blue.
byRed = *(pbyColor + 0);
byGreen = *(pbyColor + 1);
byBlue = *(pbyColor + 2);
If accessed with a byte pointer, the bytes in an OS/2 palette are accessed in
the order Blue, Green, Red, Flag.
byBlue = *(pbyColor + 0);
byGreen = *(pbyColor + 1);
byRed = *(pbyColor + 2);
byFlag = *(pbyColor + 3);
For implementation of a PCX decoder and encoder, check out the sample source
code that comes with this article. Handling the header, codec, and palette can
all be seen in pcx.cpp. The handling of the byte reversal scheme can be seen
in the Convert() routine of os2pal.cpp.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.7. The PcxPainter object ΓòÉΓòÉΓòÉ
The PcxPainter object
The PcxPainter object is derived from the BitmapPainter object. All of the
member functions called by a program are virtual functions in the BitmapPainter
object, so you could just as easily replace the PcxPainter object with a
GifPainter or TifPainter, and not have to change much of anything else in your
program. The functions of the BitmapPainter object are:
AssociateCanvas(): this routine tells the BitmapPainter object what canvas is
to be used for the uncompressed graphic. If the canvas is not large enough for
the graphic, the information outside of the canvas will be discarded.
DissociateCanvas(): this routine clears the internal pointers to the canvas.
AssociateBuffer(): this routine is used to tell the object where the encoded
graphic is in memory. Such a buffer might be created by finding the size of a
PCX file, allocating that much memory, and then reading the entire PCX file
into that buffer. In the PcxPainter object, the AssociateBuffer() routine also
checks the buffer to see if it contains valid PCX information before it accepts
the buffer. If the buffer does not contain valid information or is of an
unsupported PCX type (16 color), then the routine returns with an error.
DissociateBuffer(): this clears the internal pointers to the buffer.
PaintCanvas(): this instructs the object to take the compressed graphic
specified in AssociateBuffer(), decompress it, and display it to the canvas
specified with AssociateCanvas(). This routine also determines the palette of
the graphic, and stores it in an internal buffer.
EncodeCanvas(): For PcxPainter, EncodeCanvas() will take the entire canvas
specified with AssociateCanvas(), encodes it in PCX format, and stores it in an
internal buffer. It allocates and uses an internal buffer because the size of
the compressed graphic is not known when the routine is called. EncodeCanvas()
will return a pointer to the internal buffer, as well as the size of this
buffer.
FreeEncodeBuffer(): This causes the internal buffer that EncodeCanvas()
allocated to be deallocated.
QueryBitmapStats(): This routine looks at the information in the buffer
specified by AssociateBuffer(), and fills in the provided structure with the
bitmap width, height, and color depth.
MonoSetWhite() and MonoSetBlack(): These routines set the color index to be
used for the black or the white pixels when a monochrome bitmap is decoded.
Since the target canvas is a 256 color canvas, values from 0 to 255 may be
specified.
QueryPaletteBuffer(): This routine returns a pointer to the internal buffer
with the palette info. The palette data is stored with three bytes per palette
entry, and the bytes specify the red, green, and blue components of the color
respectively.
QueryLastErrorCode(): This returns a code for the last error encountered, and
its value can be used to look up the error code from the resource file's string
table. The codes are specified in errcodes.hpp and the error strings are
specified in game2.msg.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.8. Conclusion and News of the Future ΓòÉΓòÉΓòÉ
Conclusion and News of the Future
Well, that's about it for my second article in Gearing Up For Games. As
always, comments, flames, and questions are welcomed. I can be reached at the
email address listed in the "Contributors" section.
Next time I will probably look into threads, semaphores, timers and other
multitasking concerns. If I have time, I may start on how to draw sprites as
well.
In the future, I will be looking into the fullscreen support aspects of DIVE.
I recently added fullscreen support to a project I'm working on, and it was a
fairly simple process. It took about 15 minutes to write all the code needed
to implement fullscreen support, an hour to get the darn thing to compile
(problems with parameter passing since header files for fullscreen support
don't exist yet), and another hour working out undocumented pitfalls of
fullscreen modes. I'll be certain to give a full report in a couple of months
as availability of the Games SDK draws closer.
It looks like the Games SDK will be released through the DevCon CD subscription
program. For those of you unfamiliar with DevCon, it is subscription that
comes four times a year, and each "issue" contains several CDs with
information, toolkits, and sample code on them, as well as a paper newsletter
with articles on various aspects of developing for OS/2. I included ordering
information in my last article, so I won't repeat it here. I don't know if the
Games SDK will be released through other means other than DevCon. I think that
IBM should release it freely, but that is just my (and a lot of other people's)
opinion.
Also, I have recently learned that IBM has released joystick drivers for OS/2.
The drivers can be obtained by anonymous ftp to ftp01.ny.us.ibm.net in the
/pub/games directory. The filename is JOYSTICK.ZIP. I haven't found any
programming information for these drivers yet, but I'll be sure to fill
everyone in on what I can find as soon as I find it!
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 7.9. Whoops! ΓòÉΓòÉΓòÉ
Whoops!
Well, looks like I made a few mistakes in the code for my last article. Time to
come clean on them:
1. In game1.rc, the ICON statement should read:
ICON ID_APPMAIN game1.ico
2. The file game1.msg was not needed. GAME2 uses .MSG files however.
3. The Canvas::QueryWidth() and Canvas::QueryHeight() methods should return
USHORTs instead of SHORTs.
4. In the article itself, the colors were wrong for the picture of the
sample code's output. This happened because I did not convert the
palette of the bitmap to the system palette before I submitted it.
Compiling the Sample Code With the Watcom Compiler
I did not give instructions on how to get the sample code to compile with the
Watcom compiler (which I actually use by the way.) To use the DevCon toolkit
with Watcom, the following things must be done:
In Your C/CPP Compilations
First, for all of your C and CPP files that use the DevCon Warp Toolkit, add:
#define __IBMC__
before you include any of the DevCon header files. Note that there are two
underscores both before and after the "IBMC", not just one.
Also make sure that the compiler is looking in the \H directory of your DevCon
toolkit for header files, not in the WATCOM\H\OS2 directory.
In The File mmioos2.h
Find the section titled : "Country codes (CC), languages (LC), and dialects
(DC)."
You will notice that some of the defines in this section begin with a zero.
This causes the Watcom compiler to read these numerals as octals (as any good
ANSI compiler would <grin>). Remove these zeroes. Therefore the definition:
#define MMIO_CC_USA 001
would become
#define MMIO_CC_USA 1
This needs to be done from MMIO_CC_NONE (value of 0) to MMIO_CC_TURKEY (value
of 90).
In Your Linker setup
Don't forget to include the library mmpm2.lib when you link. This can either
be done in the IDE in the menu "Options \ OS/2 Linking Switches \2.Import,
Export and Library Switches" in the "Libraries(,):[libr]" window, or in the
command line of your linker with the statement "libr mmpm2.lib" (without the
double quotes, of course).
Also, be certain to have a large enough stack for your program. The default
stack for the Watcom IDE is about 8K I think. The MMPM/2 documentation
suggests at least a 16Kb stack, but I compile with a 32K stack.
Gearing Up For Games (Part 2) - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8. Programming the WPS Using the UICL ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
Programming the WPS Using the UICL
Written by Juergen Riedl
Introduction
About one year ago I posted a question onto the net asking whether or not it is
possible to develop WPS classes with IBM's User Interface Class Libraries
(UICL), but even IBM itself couldn't give me an answer, so I forgot about it.
In April this year, however, I was offered by the OS/2 User Group of the
Technical University of Munich (Bavaria / Germany) to give a review of the book
about the UICL entitled OS/2 C++ Class Library, Power GUI Programming with C
Set++ by Leong, Law, Love, Tsuji and Olson. I remembered my wish a year ago,
started my first simple steps to program the WPS using the UICL, stumbled into
some mysterious probems. But with some luck I got it to work ("1% inspiration
but 99% transpiration", Thomas Edison).
This submission is the attempt to share my experiences with you, in the hope to
enable you to easily write applications which are completely integrated into
the WPS using the UICL. If this is to your taste then follow me on the journey
to see that it is not too difficult.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.2. The Paradigms ΓòÉΓòÉΓòÉ
The Paradigms
Frequently, IBM has created sophisticated APIs but never invested sufficient
effort to publish the required documents to enable programmers to use them.
This situation has slightly changed for the WPS [1, 2] and has been
considerably improved for the UICL [3].
The WPS represents the paradigm which enables you to use your computer in an
document-centered fashion. But due to the lack of good guidance, developing
WPS classes is a rather difficult task. The PM API is abstracted from you; you
don't see any function responsible for message processing; you don't even see
an easy way to extent their functionality. In my opinion this is the reason
why 99% of all OS/2 applications follow the old PM style paradigm. Any WPS
programmer will be seen as a guru, which in fact they are. <grin>
I made my first steps of WPS programming guided by the book Client/Server
Programming with OS/2 2.1 by Orfaly and Harkey. But I didn't like WPS
programming very much - even small bugs in my classes required rebooting the
machine. So it was burdensome. This changed dramatically with the advent of
OS/2 3.0 Warp which designed the WPS as a DSOM server. Instead of rebooting
the machine as before, the WPS was usually the one restarted. Along the way, I
learned to like the UICL, which presented the obvious question: why should I
program in the old PM style after having tasted the sweet flavour of the UICL?
At a first glance, the UICL appears to be a wrapper of PM. If you take the
time, though, you will realize that it is more: it provides the means of
creating sophisticated classes with few lines of code instead of hundreds as
the pure PM programmer is forced to do. Even though the UICL is that powerful
it seems to me to contradict the aim of the WPS, which is to support the
document-centered paradigm. All of the "programs" should be seamlessly
integrated into the shell, like extensions; no one should start any application
first and generate the document afterwards as in the past. But with the UICL
the obvious way is to generate an EXE which will be attached to the usual
program notebook of the WPS. Wouldn't it be nice to be able to open a
customized notebook of this application as any other WPS object?
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.3. Mastering the First Step ΓòÉΓòÉΓòÉ
Mastering the First Step
You have read the file README.1ST and set up your environment accordingly? All
right, lets start.
What do we want to do? We want to develop a WPS application comprising a
notebook and a frame window. Will this application be a "killer application?"
No, it is only a sample to show how to implement the WPS and UICL combination.
The development of the "killer application" is up to you. But it will become
far easier in my opinion.
We will begin by subclassing WPAbstract. WPAbstract provides two notebook
pages, the Window page and the General page. For the first step, we will
extend this class to open an ordinary "Hello World" frame window by double
clicking on its icon. After that we will examine how to add customized notebook
pages to the already defined ones. And, of course, all of this will be done
using the UICL!
Since we are dealing with the WPS we must use the SOM IDL. (The new
VisualAge++ compiler may change this with its Direct To SOM capability) But it
is not difficult to follow the code; examine the file OS2UG.IDL (for
information on SOM and WPS please read EDM/2 issues 2-8 and 2-9):
interface XWPS : WPAbstract
{
#ifdef __SOMIDL__
implementation {
//# Class Modifiers
majorversion = 1;
minorversion = 2;
dllname = "os2ug.dll";
metaclass = M_XWPS;
callstyle = oidl;
passthru C_xih_before =
"#include <os2.h>";
//# Method Modifiers
wpModifyPopupMenu : override;
wpMenuItemSelected: override;
wpOpen : override;
wpAddSettingsPages: override;
};
#endif // __SOMIDL__
};
As you might assume looking at the class declaration interface, XWPS :
WPAbstract sounds like class XWPS : public WPAbstract in C++. Outside of the
implementation block, neither additional instance variables nor functions are
declared. For that reason, no release order section is required. To be
compliant with the WPS call style, set callstyle = oidl. If you will write
CORBA-compliant DSOM classes, you must set callstyle = corba. But this doesn't
apply to WPS GUI classes yet. During this article, we will override some WPS
instance methods, which begin with the letters wp. For the first step, we will
focus on three methods; the method wpAddSettingsPages() is the subject of the
second step. Each of them will be discussed separately.
Now take a look onto the metaclass declaration interface M_XWPS:
interface M_XWPS
// same as interface M_XWPS: M_WPAbstract
{
#ifdef __SOMIDL__
implementation {
//# Class Modifiers
majorversion = 1;
minorversion = 2;
callstyle = oidl;
//# Method Modifiers
wpclsQueryStyle: override;
wpclsQueryTitle: override;
wpclsQueryDefaultView: override;
};
#endif // __SOMIDL__
};
Here you see that SOM is slightly different from C++. It provides different
types of classes and subsequently different types of methods: class methods and
instance methods. Class methods are tied to metaclasses. Metaclasses are
responsible for the management of class resources, and they provide the "bed"
for the instance of a class like you do with the constructor of a C++ class.
For the first step we need to override three class methods, which begin with
the letters wpcls. Each of them will be discussed separately.
After you have declared the interfaces in your IDL file, you will run the SOM
compiler SC against it. Enter SC OS2UG.IDL to compile the file. The SOM
compiler generates an XH, an XIH, a CPP and a DEF file. Because it is common
programming style to separate each function into a separate file, please do so
accordingly. Unfortunately, the SOM compiler not only generates declarations,
but also definitions within its header files; later you have to write a source
file which #include's all of the separate files.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.4. Overriding wpclsQueryStyle ΓòÉΓòÉΓòÉ
Overriding wpclsQueryStyle
While developing WPS classes, you need to register and deregister them many
times. You can avoid this by disabling the generation of a template of your
WPS class. If you do not, you can only get rid of the template by rebooting
into a command shell without the WPS running and delete the corresponding
DLL's. With an additional reboot you can continue development. I disable the
generation of a template to make life easier; this is achieved as follows (see
the file m_qstyle.cpp):
SOM_Scope ULONG SOMLINK wpclsQueryStyle(M_XWPS *somSelf)
{
/* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
M_XWPSMethodDebug("M_XWPS","wpclsQueryStyle");
return (M_XWPS_parent_M_WPAbstract_wpclsQueryStyle(somSelf)
| CLSSTYLE_NEVERTEMPLATE); // no templates
} // END wpclsQueryStyle()
It returns the parents style or'd with the style CLSSTYLE_NEVERTEMPLATE.
That's all you need. The result is that now the template checkbox on the
General page is not available. Thus you can deregister your class after
deleting the instance and delete the DLL without the need to reboot your
machine.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.5. Overriding wpclsQueryTitle ΓòÉΓòÉΓòÉ
Overriding wpclsQueryTitle
If you like to have a default title of your new class you will set it here (see
the file m_qtitle.cpp).
SOM_Scope PSZ SOMLINK wpclsQueryTitle(M_XWPS *somSelf)
{
/* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
M_XWPSMethodDebug("M_XWPS","wpclsQueryTitle");
return (ClassTitle);
} // END wpclsQueryTitle()
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.6. Overriding wpclsQueryDefaultView ΓòÉΓòÉΓòÉ
Overriding wpclsQueryDefaultView
When you double click on the icon, which view should be opened? The settings
notebook or the frame window? Our sample class opens a frame window (see the
file m_qdefvw.cpp). This is done by declaring the value OPEN_XWPS1 (see the
file os2ug.h) which is one of three possible frame windows:
SOM_Scope ULONG SOMLINK wpclsQueryDefaultView(M_XWPS *somSelf)
{
/* M_XWPSData *somThis = M_XWPSGetData(somSelf); */
M_XWPSMethodDebug("M_XWPS","wpclsQueryDefaultView");
return (OPEN_XWPS1);
}// END wpclsQueryDefaultView()
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.7. Overriding wpModifyPopupMenu ΓòÉΓòÉΓòÉ
Overriding wpModifyPopupMenu
When you click with mouse button 2 (default right) on your application's icon,
you would like to find a menu reflecting your default view. This will be added
to the overridden function above (see the file modpupmu.cpp):
SOM_Scope BOOL SOMLINK wpModifyPopupMenu(XWPS *somSelf,
HWND hwndMenu,
HWND hwndCnr,
ULONG iPosition)
{
zString ModulePathName; // DLL Module path and name
HMODULE hmod; // DLL MODULE handle
/* XWPSData *somThis = XWPSGetData(somSelf); */
XWPSMethodDebug("XWPS","wpModifyPopupMenu");
// Get Module Name and Handle
const IDynamicLinkLibrary dynid(cDllName); // dll name: OS2UG.DLL
hmod = dynid.handle();
// Insert "Hello OS2UG" into Open Menu
if (!somSelf->wpInsertPopupMenuItems( hwndMenu, 0,
hmod, ID_OPENMENU, WPMENUID_OPEN)) {
DebugMsg("Error in wpModifyPopupMenu()",ModulePathName );
}
return (TRUE);
} // END wpModifyPopupMenu()
To retrieve the module handle of the DLL which contains the binaries for your
popup menu I chose to use an instance of IDynamicLinkLibrary, a class of the
UICL. The usual approach would be to call the SOM function
somLocateClassFile(), but this doesn't work on my machine (your mileage may
vary):
ModulePathName = (*SOMClassMgrObject)
.somLocateClassFile( SOM_IdFromString(ClassTitle),
XWPS_MajorVersion,
XWPS_MinorVersion);
DosQueryModuleHandle( ModulePathName, &hmod);
It would be a nice exercise for you to try both methods. <grin>
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.8. Overriding wpMenuItemSelected ΓòÉΓòÉΓòÉ
Overriding wpMenuItemSelected
Now you have decided to open the "Hello OS2UG" view and the WPS processes the
overridden method wpMenuItemSelected() (see the file muimsel.cpp). Here you
will call wpViewObject() to open a view. This function calls your application's
frame window routine:
SOM_Scope BOOL SOMLINK wpMenuItemSelected(XWPS *somSelf,
HWND hwndFrame,
ULONG ulMenuId)
{
/* XWPSData *somThis = XWPSGetData(somSelf); */
XWPSMethodDebug("XWPS","wpMenuItemSelected");
switch( ulMenuId )
{
case OPEN_XWPS1:
somSelf->wpViewObject( hwndFrame, OPEN_XWPS1, 0);
break;
case OPEN_XWPS2:
somSelf->wpViewObject( hwndFrame, OPEN_XWPS2, 0);
break;
case OPEN_XWPS3:
somSelf->wpViewObject( hwndFrame, OPEN_XWPS3, 0);
break;
default:
return (XWPS_parent_WPAbstract_wpMenuItemSelected
(somSelf, hwndFrame, ulMenuId));
}
return TRUE;
} // END wpMenuItemSelected()
Have you discovered that you can open three different views OPEN_XWPS1,
OPEN_XWPS2 and OPEN_XWPS3? These start a frame window in either a separate
thread, within the WPS thread of your notebook, or in a separate process,
respectively.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.9. Overriding wpOpen ΓòÉΓòÉΓòÉ
Overriding wpOpen
Here you see the transition from the WPS world to your application's world, the
"Hello WPS" frame window (see the file open.cpp). Here you call one of the
CreateTUM_OS2_UGView*() methods, which are responsible for creating your frame
window:
SOM_Scope HWND SOMLINK wpOpen(XWPS *somSelf, HWND hwndCnr,
ULONG ulView, ULONG param)
{
/* XWPSData *somThis = XWPSGetData(somSelf); */
XWPSMethodDebug("XWPS","wpOpen");
switch (ulView)
{
case OPEN_XWPS1:
ptrIcon = somSelf->wpQueryIcon();
return CreateTUM_OS2_UGViewA(somSelf);
break;
case OPEN_XWPS2:
ptrIcon = somSelf->wpQueryIcon();
return CreateTUM_OS2_UGViewB(somSelf);
break;
case OPEN_XWPS3:
ptrIcon = somSelf->wpQueryIcon();
return CreateTUM_OS2_UGViewC(somSelf);
break;
} // end switch (ulView)
return (XWPS_parent_WPAbstract_wpOpen
(somSelf, hwndCnr, ulView, param));
} // END wpOpen()
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.10. Creating Your Frame Window ΓòÉΓòÉΓòÉ
Creating Your Frame Window
If you're wondering why there hasn't been a lot of UICL usage, do not worry -
to escape the WPS programming style a bit of work has to be done. But this was
only a few lines of code; now you can start to fly. If you are ready to take
off into the UICL heaven, let's begin.
Within the function CreateTUM_OS2_UGViewB() you have the choice to create your
frame window similar to the PM style (here in pseudo code, the actual code is
in view_b.cpp):
HWND CreateTUM_OS2_UGViewB(XWPS * somSelf){// view_b.cpp
get the module handle;
create the customized frame window;
extract the frame window handle;
somSelf->wpRegisterView(frame window handle, frame window title);
return (frame window handle);
}// end CreateTUM_OS2_UGView()
Or you may create a separate thread for your application with the advantage of
programming your application as usual in UICL. First, you create an EXE file.
After finishing, you rename the main() function to something else, which is
called by the thread; finally, you change some lines of code as illustrated
below (in pseudo code, the actual code is in view_a.cpp and threadm.cpp).
Please compare threadm.cpp with main.cpp:
HWND CreateTUM_OS2_UGViewA(XWPS * somSelf){// view_a.cpp
set up a semaphore;
IThread myThread(threadMain, semaphore adress);
wait until semaphore is posted but no longer than x seconds;
obtain frame window handle;
somSelf->wpRegisterView(frame window handle, frame window title );
return (frame window handle);
}// end CreateTUM_OS2_UGView()
void threadMain(void * arg) // threadm.cpp
{
obtain the handle to the binary of the resource
create customized frame window;
extract the frame window handle;
post frame window handle;
IApplication::run();
}// end threadMain()
The third choice is to start your frame window as separate process. Here you
have to use named semaphores. The pseudocode is identical with the threaded
example with the exception that instead of a thread (see the file view_a.cpp)
the process will be started by DosExecPgm() (see the files view_c.cpp and
main.cpp). Here is where the second part of the project comes into play.
Look back at the discussion of the wpOpen() method: you may create a frame
window in another thread, the same thread, as well as in another process within
the same sample application. The best way to illustrate the differences is to
start the clock with the second-hand enabled. I have programmed the frame
window with the choice of "bigjob" being either multithreaded or running within
the same thread. Start "bigjob" and examine what happens with both the
second-hand and the WPS when you try to select a different application!
Now we will add some customized notebook pages to the WPS notebook. The page
contains a "Welcome" bitmap and an MLE instance. [Note: the bitmap is a
customized OS2LOGO.BMP, some of my friends got shocked seeing the "OS/2 Warp 2
Alpha" during start-up of my machine. It is only a joke; please do not send
any email asking if I know any secrets about a new release of OS/2.]
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.11. Overriding wpAddSettingsPages ΓòÉΓòÉΓòÉ
Overriding wpAddSettingsPages
Here you see an excerpt of adsetpgs.cpp. It is that simple to add additional
pages to your WPS notebook. Is it really that simple? Yes, but you need a
workaround for some strange behaviour which I noticed on my machine at least.
If I would omit the IString instance the notebook would be reduced in size;
thus none of the notebook pages are shown in entirety (see the note in the file
adsetpgs.cpp).
SOM_Scope BOOL SOMLINK wpAddSettingsPages(XWPS *somSelf,
HWND hwndNotebook)
{
/* XWPSData *somThis = XWPSGetData(somSelf); */
XWPSMethodDebug("XWPS","wpAddSettingsPages");
Boolean rc;
IString
s1("workaround for strange behaviour. Keep this string her!");
// pages are added in reverse order, that is the last page first
rc = somSelf->wpAddObjectGeneralPage(hwndNotebook);
if (!rc) {
DebugMsg("Error", "wpAddObjectGeneralPage()");
} // endif
addMLENotebookPage( hwndNotebook );
rc = somSelf->wpAddObjectWindowPage(hwndNotebook);
if (!rc) {
DebugMsg("Error", "wpAddObjectWindowPage()");
} // endif
addFirstNotebookPage( hwndNotebook);
return (rc);
} // END wpAddSettingsPages()
By principle any function to add to a UICL notebook page looks the same. Let's
have a look on the pseudo code:
void addAnyNotebookPage( HWND * notebook)
{
prepare the notebook and the notebooks frame window handle;
if a UICL frame window proxy doesn't exist create one;
if a UICL notebook window proxy doesn't exist create one;
prepare a notebook settings instance;
add settings instance as first notebook page;
attach a customized page settings handler to the notebook;
} // END addAnyNotebookPage()
The customized page handler takes care that the page is initialized only once,
when the page is first shown. Only the page which will be shown will be
instantiated. Thus the opening of a notebook is much quicker than you creating
all page instances at once. I recommend this technique, because the user
shouldn't be forced to wait too much.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.12. Conclusion ΓòÉΓòÉΓòÉ
Conclusion
So my friend, you have followed me to the end of the journey. I hope you will
be able to create the killer application, fully integrated into the WPS with
the help of the UICL. The UICL improves the programming of OS/2 allowing you
to develop applications quicker and with less effort.
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 8.13. References ΓòÉΓòÉΓòÉ
References
[1] Client/Server Programming with OS/2 2.1 by Robert Orfali and Dan Harkey,
VNR / ISBN 0-442-01833-9
[2] OS/2 Warp Workplace Shell API by Mindy Pollak, Wiley / ISBN 0-471-03872-5
[3] OS/2 C++ Class Library Power GUI Programming with C-Set++ by Kevin Leong,
William Law, Robert Love, Hiroshi Tsuji, and Bruce Olson, VNR ISBN
0-442-01795-2
Programming the WPS Using the UICL - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 9. 32-Bit I/O With Warp Speed ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 9.1. Introduction ΓòÉΓòÉΓòÉ
32-Bit I/O With Warp Speed
Written by Holger Veit
Introduction
Well, I have a little bit of a bad feeling. What I am going to describe in
this article is something that should not be possible at the level of user
application programs: direct I/O. This is the ability of a user program to
talk to hardware resources directly, not controlled or even monitored by the
operating system.
Although it might have been common practice in a simple program loader like
DOS, it is normally not a good idea in a modern multitasking or multi-user
system. In fact, OS/2, Windows NT, and the various UNIX derived operating
systems, spend considerable efforts to hide this practice from user
applications, or explicitly prohibit it. The reasons for that are obvious and
well known:
User programs could access system resources, that means here hardware
devices, in an uncoordinated or uncooperative way, and could therefore
severely influence or even damage data integrity, system stability, and
security.
While the operating system tries to distribute the limited resources in a
fair way among the various competitors, a program that circumvents the
care of the operating system, could grab such a resource exclusively.
Even worse, it might struggle with the operating system for control,
which will unlikely have good consequences on the overall system
throughput.
Needless to say, a malign process like a computer virus could use a
feature like direct I/O to intentionally destroy data. However, even
with good intention, a user program is not immune against software bugs
that might not only crash the program itself but also take the system
with it into the abyss.
On the other hand, people usually do not want to have I/O access to write
improved support for complicated disk or video devices. Rather they have
simple I/O devices like data acquisition cards, parallel I/O boards, EPROM
programmer adapters or alike, that do not come with OS/2 support at all.
Writing a full-blown OS/2 device driver in order to reuse an old 8255 port
card seems like shooting sparrows with cannons. In such a case, where neither
interrupt handling or DMA, nor physical access to adapter memory is involved,
direct I/O appears to be a feasible alternative. In the following chapter, we
will look at the official methods that OS/2 offers to do I/O.
32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 9.2. Doing Port I/O: The Front Doors ΓòÉΓòÉΓòÉ
Doing Port I/O: The Front Doors
Device drivers
No doubt, as was already stated, a device driver is the real solution. Keep
critical tasks away from the user is the rule of the game. The path to this is
quite stony, however.
As often criticized, device drivers in OS/2 are still 16 bit code. This has
several disadvantages.
You need to code entirely in assembler, or find a C compiler that still
produces 16 bit code. Most of the standard drivers that come with OS/2
were built with either MASM 5.1 or MSC 6.0. It is not only the problem
that IBM relies on products of a competitor here, but simply that these
products are no longer available in stores, and the successors no longer
support OS/2. Fortunately, the recent, widely available Watcom 10.0
compiler is usable for device driver development.
Coding in 16 bit throws the developer back into the stone age where he
has to fight against 64K segments, far and near calls, moving around
selectors and grouping segments in a certain order.
Nevertheless, one could think about writing a device driver that you can use
to read and write I/O ports by issuing special DosDevIOCtl instructions.
Surprisingly, this is an unnecessary enterprise! Not many OS/2 users know
that every stock OS/2 system comes with a device driver that comes with such a
functionality: TESTCFG.SYS.
Besides some other functions that are beyond the scope of this article,
TESTCFG.SYS offers two ioctls, one for reading I/O ports and another one for
writing. See table 1 for the description of the functions and the simple
program fragment in figure 1 for an example.
Device name "TESTCFG$"
Description Read data from I/O port
IOCTL Category 0x80
IOCTL Function 0x41
Parameter packet struct {
USHORT portaddr;
USHORT size;
} param
Data packet struct {
ULONG dataread;
} data;
Remarks size=1: read 8-bit
size=2: read 16-bit
size=3: read 32-bit
Description Write data to I/O port
IOCTL Category 0x80
IOCTL Function 0x42
Parameter packet struct {
USHORT portaddr;
USHORT size;
ULONG datawrite;
} param
Data packet none
Remarks size parameter same as for function 0x42 param packet in
"Writing OS/2 2.1 Device Drivers in C" book is wrong!
Table 1: Ioctl API of TESTCFG.SYS for doing direct I/O
/* direct I/O with TESTCFG.SYS */
#define INCL_DOSFILEMGR
#define INCL_DOSDEVIOCTL
#include <os2.h>
HFILE fd;
ULONG action, len;
APIRET rc;
struct {
USHORT port;
USHORT size;
} par;
struct {
ULONG data;
} dta;
rc = DosOpen("/dev/testcfg$",
&fd, &action, 0,
FILE_NORMAL, FILE_OPEN,
OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE,
(PEAOP2)NULL);
/* check error code.... */
par.port = 0x84; /* use a mostly harmless port */
par.size = 1; /* read byte */
rc = DosDevIOCtl(fd, 0x80, 0x41,
(PULONG)&par, sizeof(par), &len,
(PULONG)&dta, sizeof(dta), &len);
/* check error code.... */
printf("Data was 0x%lx\n", dta.data);
rc = DosClose(fd);
/* needless to say: check.... */
Figure 1: Sample code to read a port through TESTCFG.SYS
There is one drawback, and we will hear this argument again real soon: it is
slow. Why?
Now see, we are calling this function from a 32 bit user program. The
DosDevIOCtl() will enter the kernel through a call gate which is some kind of
a protected door. The kernel will then first check the validity of the
parameter and data packets, identify the target driver to perform this
function, and then call the appropriate driver entry point. Note the driver
is 16 bit code, so the kernel must convert the addresses of the parameter and
data packets from 0:32 bit user space addresses to 16:16 bit device driver
addresses. Finally, the driver itself must decode the command and dispatch it
to its routines.
I once tried to trace such an ioctl call with the kernel debugger, and
eventually gave up counting after following some hundred instructions without
seeing any driver code. Compare this with a single IN or OUT instruction.
That's bureaucracy!
IOPL Segments
The second method is actually a leftover from earlier OS/2 1.X versions, hence
it is a 16 bit technique as well.
Let me elaborate here a bit on the method used to prevent I/O access by user
programs. The Intel 286 and later (386, 486, Pentium) processors can execute
code at four different privilege levels. Because they are nested and usually
drawn as concentric circles, these levels are frequently referred to as
privilege rings (or protection rings). Ring 0 is the level with the highest
privilege, and ring 3 has the lowest privilege (see figure 2).
Figure 2: The privilege rings and their use in OS/2
If a process wants to run with a higher privilege than the one it currently
has, it must go through a special gate; one might also compare a gate with a
tunnel or "wormhole". There are several types of gates such as interrupt,
trap, or task gates. The only interesting type for us is the call gate. A
call gate allows a one-way transfer of execution from a segment with some
privilege to another one with same or higher privilege. The other direction,
that is from a "trustworthy" high-privileged code segment to a less trusted
lower-privileged segment, is not possible. See figure 2. Figure 3: Allowed
and forbidden transactions with call gates
Two bits in the processor status register (the IOPL field) determine the level
that is necessary to execute I/O CPU instructions. Any code with less than
this privilege level will trigger an exception at the first attempt to execute
such an instruction. Table 2 lists the affected instructions. Certain
instructions will even cause an exception if the process has the privilege to
I/O. These instructions require ring 0 privilege. Table 2 also lists these
instructions (386 processor).
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéInstruction is protected and causes an ΓöéAffected instructions Γöé
Γöéexception... Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöéif not in Ring 0 ΓöéLIDT, LGDT, LMSW, CLTS, HLT MOV DR*, regΓöé
Γöé Γöé/ MOV reg, DR* MOV TR*, reg / MOV reg, Γöé
Γöé ΓöéTR* MOV CR*, reg / MOV reg, CR* Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöéif in Real Mode or in Virtual 8086 Mode ΓöéAll the above plus LTR, STR, LLDT, SLDT,Γöé
Γöé ΓöéLAR, LSL, VERR, VERW ARPL Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöéif not at IOPL privilege level or higherΓöéAll ring 0 instructions plus OUT, INS, Γöé
Γöé(in Protected Mode) ΓöéOUTS, REP INS, REP OUTS STI, CLI Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöéif not at IOPL privilege level or higherΓöéAll ring 0 and Virtual 8086 Mode Γöé
Γöé(in Virtual 8086 Mode) Γöéinstructions plus INT n (Note 1) PUSHF, Γöé
Γöé ΓöéPOPF, STI, CLI, IRET (Note 2) Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
Note 1: INT 3 (opcode 0xcc) and INTO are not affected
Note 2: I/O instructions are enabled or disabled by the I/O permission map in
the 386 task state segment
Table 2: Privileged Instructions
In OS/2, the required privilege level for I/O is ring 2 or better, and tough
luck, any user process only runs in ring 3 (figure 2).
In order to get a controlled way to do I/O, the OS/2 developers provided a
method to execute 16 bit code at ring 2 level. When the linker produces an
executable from several object files, it accepts a special attribute for code
segments under certain circumstances. This attribute is named IOPL and is
specified in the segment declaration section of a linker definition file
(Consult appropriate linker documentation). The linker then annotates the
code in a way that every call of a routine in this IOPL segment will be
directed through a call gate, rather than a simple call. When such a program
is loaded into memory for execution, the loader code in the kernel will
generate a R3->R2 call gate for each target called in an IOPL segment (see
call gate X in figure 3).
Each time such a call gate is entered, the processor will gain ring 2
privilege and lose it again when leaving by a normal return instruction.
Apparently, this looked like a feature which could be abused, so the IBM
developers restricted it in a way that only segments in a DLL can get the IOPL
attribute. This appears to be a built-in feature of the program loader, not
just the linker, as patching the appropriate tables in the executable will not
work.
This restriction is not a bad idea, as it is now no longer possible to make an
executable disguising as a normal program, but doing I/O inside. There must
be an accompanying DLL, to arouse suspicion - or at least should do so.
This could have been an almost ideal way for moderate I/O - if IBM had
provided a similar method for 32 bit applications as well. There is no
restriction in the processor itself concerning 32 bit I/O, as one might
suspect; it is an intentional limitation. Since IBM will not support 16 bit
software any longer in OS/2 for the PowerPC, those unsecure interfaces will
disappear in the future.
Nevertheless, you can call routines in such a 16 bit IOPL DLL from a 32 bit
executable, and there are several example files floating around in various FTP
archives. The key item here is thunking. The main problem with calling code
of another size gender is that the program counter as well as the stack
pointer needs to be adjusted to the corresponding other size. If address
parameters are passed through the stack, these addresses need to be converted
as well. This is what a thunking routine does.
Usually the compiler generates such routines automatically when a 16 bit
routine is declared, and this is why many high- level programmers do not
encounter them at all. However, even if they seem to be invisible, they
nevertheless contribute a considerable share to performance degradation if an
I/O routine in the IOPL DLL is called from a 32 bit application.
32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 9.3. Doing I/O: Searching for Mouse Holes ΓòÉΓòÉΓòÉ
Doing I/O: Searching for Mouse Holes
In the last section, we have seen that it is possible to do direct I/O with the
already available facilities. The difficulty is just the excessive overhead
that makes their use quite unattractive, and with the text of the preface still
in mind, there can be no doubt that this is not incidental.
However, as some of you might know about my ambitious pet project, it was
indispensable for me to find an extremely fast alternative to the above stuff.
Although I prefer writing a device driver for that kind of applications, it
seemed entirely impossible to put a complete Xserver into a 16 bit device
driver (that beast, with PEX, is as large as 2 MB - 32 bit code!). Moving only
the critical parts into a driver might work; unfortunately the XFree86 people
are too creative for me, so it would be expectable that I'd be hurrying to get
their recent changes integrated for the rest of my life.
So let us discuss possible alternatives.
Outwitting the Program Loader?
As we have seen in the discussion of the IOPL mechanism, the bottleneck is the
thunking code. Interestingly, there exist types of call gates that can mediate
among 32 and 16 bit code and do the necessary conversion of the program counter
and stack pointer automatically. Unfortunately, the program loader refuses to
make them for us. Likewise, there seems to be no chance to have it create a
32->32 bit call gate. A brute force approach could be trying to identify the
call gates it made for us and redirect them to the routines that we want to run
with privilege. Since we need certain instructions to manipulate the GDT or
LDT (more on that later), this is not possible from a user program, because the
kernel protects these structures well in a ring 0 segment. Similar to the
restriction not to pass a call gate in the wrong direction, a process cannot
read, let alone write, data of a higher ring level. This is not a real
problem, if we have an accomplice with sufficient rights to do the dirty work
for us: a device driver.
However, besides being a bad hack, such a solution is still half-hearted. Once
we find a method to manipulate call gates, we no longer need to have this code
separated in a DLL, as with the IOPL anachronism, but we could keep it in the
executable itself. Furthermore, while we are on this way, couldn't we just
manipulate the code segment of the user process into a ring 0 one? Let us
think about this possibility.
User Processes at Ring 0?
During reading, you might have thought about the question how the processor
knows which privilege the currently executed code has, and where it keeps this
information. This is pretty simple in protected mode: somewhere in memory
there are two tables that describe the location, size and properties of each
memory segment. They are called global descriptor table (GDT) and local
descriptor table (LDT). While the GDT describes system wide structures, there
is usually an LDT for each process in the system. Two special registers of the
CPU, GDTR and LDTR, point to the beginning of the tables. Each table is an
array with elements of eight bytes in size. The index into these arrays is
fairly simple: it is formed from the upper 13 bits of the 16 bit segment
registers (CS, DS, ES, SS, FS, GS). Bit 2 of these registers distinguishes
between LDT and GDT, and the two lowest bits describe the current privilege the
CPU is running. What is most important is that any segment descriptor in the
tables also contains two bits that determine the privilege level the code runs
under.
So the way to go seems clear: get the content of the CS register, find the
corresponding GDT or LDT entry, and switch the privilege bits to ring 0. This
is possible. However, this game will likely end very fast with a trap and the
register display on the text mode screen. Why?
We have seen in figure 3 that privileged ring 0 code will never execute less
privileged code. However, certain system or application DLLs required by the
user program still have ring 3 level. So the unfortunate consequence is: if
your user program has privileges, it will lose the ability to call several
system functions. The immediately upcoming flash of an idea of promoting the
system and user DLLs to the same level as well, is hopefully not meant
seriously, as it will end up with all software running privileged.
It therefore appears that any trick to raise the privilege of the user process
introduces more problems rather than solving them. Let us try to approach the
problem from a totally different side. Maybe we could reduce the overhead of
performing functions in a device driver. A Back Door into a Driver:
DevHlp_DynamicAPI
Time to dive a bit deeper into a device driver. The kernel provides a set of
routines known as device helper functions to a device driver. One of these
helpers appears particularly attractive, as it promises to create a ring 0 gate
directly into a device driver. So the idea is to build the I/O functions into
the driver and create such a dynamic API entry point. This will return a GDT
selector that a user process can enter with an indirect intersegment call
instruction. Estimating the overhead, this should be considerably faster than
the bureaucratic way of TESTCFG.SYS.
At least that's how it works in theory.
In fact, I programmed it this way, and it worked, but it did not even reach the
slow speed of TESTCFG.SYS. Careful single stepping showed the following: the
DevHlp_DynamicAPI created the call gate, but the gate did not point straight
to the driver routine I wrote for the I/O access. Instead, it pointed to
somewhere in the kernel, into a routine DYNAM_API_4. This entry point then
performed almost all the fiddling I observed earlier when tracing the ioctl of
TESTCFG.SYS. What was even worse was what the "4" in the label of the first
routine told me. I had broached a scarce resource. Analysis showed that there
are only 16 of these entry points available system wide, and mine was already
the fifth one in use. I have not the slight idea about the other four clients,
but it does not seem to be a good idea to deliberately use up one of those
expensive and rare interfaces.
But in principle, the idea was correct.
32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 9.4. /DEV/FASTIO$ - the Final Way ΓòÉΓòÉΓòÉ
/DEV/FASTIO$ - the Final Way
Okay. We just managed to get a transforming (32->16bit) call gate, that just
happens to point to the wrong address. It was a matter of seconds to find the
address of the corresponding GDT entry, and redirect it to the expected
position. A kernel debugger is really a neat tool for the hacker. It worked!
At this point, calling the DevHlp_DynamicAPI function becomes useless, and will
just occupy a later unusable entry point in the kernel. A quick look into the
list of device helper functions offers the function DevHlp_AllocGDTSelector.
We acquire a default GDT selector for exclusive use by the driver, and "adjust"
it to form a 32->16 bit R3->R0 call gate into the I/O routine section of the
driver.
Have a look at the code fragment in the FASTIO$ driver (figure 4) which does it
all.
.386p
_acquire_gdt proc far
pusha
mov ax, word ptr [_io_gdt32] ; get selector
or ax,ax
jnz aexit ; if we didn't have one
; make one
xor ax, ax
mov word ptr [_io_gdt32], ax ; clear gdt save
mov word ptr [gdthelper], ax ; helper
push ds
pop es ; ES:DI = addr of
mov di, offset _io_gdt32 ; _io_gdt32
mov cx, 2 ; two selectors
mov dl, DevHlp_AllocGDTSelector ; get GDT selectors
call [_Device_Help]
jc aexit ; exit if failed
sgdt qword ptr [gdtsave] ; access the GDT ptr
mov ebx, dword ptr [gdtsave+2] ; get lin addr of GDT
movzx eax, word ptr [_io_gdt32] ; build offset into table
and eax, 0fffffff8h ; mask away DPL
add ebx, eax ; build address in EBX
mov ax, word ptr [gdthelper] ; selector to map GDT at
mov ecx, 08h ; a single entry (8 bytes)
mov dl, DevHlp_LinToGDTSelector
call [_Device_Help]
jc aexit0 ; if failed exit
mov ax, word ptr [gdthelper]
mov es, ax ; build address to GDT
xor bx, bx
mov word ptr es:[bx], offset _io_call ; fix address off
mov word ptr es:[bx+2], cs ; fix address sel
mov word ptr es:[bx+4], 0ec00h ; a r0 386 call gate
mov word ptr es:[bx+6], 0000h ; high offset
mov dl, DevHlp_FreeGDTSelector ; free gdthelper
call [_Device_Help]
jnc short aexit
aexit0: xor ax,ax ; clear selector
mov word ptr [_io_gdt32], ax
aexit: popa ; restore all registers
mov ax, word ptr [_io_gdt32]
ret
_acquire_gdt endp
Figure 4: Initialization routine of FASTIO$ driver
Since a device driver is initialized in ring 3, this routine does not work
during startup. Rather, the driver will call this code once the first time
some client opens the device. Thus, to use the driver, a small routine
io_init() needs to be called first. Refer to the file iolib.asm that comes
with this issue of EDM/2.
A final improvement: Usually, C code passes arguments on the stack. A call
gate can be configured to copy these parameters over to the new ring. But why
should we do this? For really fast I/O access we pass the data in registers.
This allows for direct replacement of I/O instructions in assembler code by a
simple indirect call as shown in figure 5. The address of the indirect call is
set up by the above mentioned io_init() procedure.
EXTRN ioentry:FWORD
:
MOV DX, portaddr
MOV AL, 123
MOV BX, 4 ; function code 4 = write byte
CALL FWORD PTR [ioentry]
:
Figure 5: Calling I/O from assembler
If the code needs to be called from C, we simply write a small stub that wraps
a stack frame envelope around it, just as shown in figure 6.
; Calling convention:
; void c_outb(short port,char data)
;
;
PUBLIC _c_outb
PUBLIC c_outb
_c_outb PROC
c_outb:
PUSH EBP
MOV EBP, ESP ; set standard stack frame
PUSH EBX ; save register
MOV DX, WORD PTR [EBP+8] ; get port
MOV AL, BYTE PTR [EBP+12] ; get data
MOV BX, 4 ; function code 4 = write byte
CALL FWORD PTR [ioentry] ; call intersegment indirect 16:32
POP EBX ; restore bx
POP EBP ; return
RET
ALIGN 4
_c_outb ENDP
Figure 6: A C callable I/O function
The file iolib.asm contains a set of functions c_inX() and c_outX() for using
I/O from any 32 bit compiler that supports the standard stack frame. The files
iolib.a and iolib.lib are precompiled versions; the file iolib.h contains the C
prototypes.
In the complete driver, I gave up a small amount of the theoretically reachable
performance. There are six basic I/O operations: IN and OUT instructions exist
for transferring bytes, 16 bit words and 32 bit long words. To become really
fast, one would have to provide a separate GDT selector for each of them. In a
typical OS/2 system, this should not be a problem. However, if now everyone
would start to add more routines, each with its own entry point, this resource
could become rather quickly a scarce one. So I spent a function code, to be
passed in the BX register, to multiplex the six functions into a single GDT
selector. Refer to the io_call entry point in the fastio_a.asm driver source
file.
32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 9.5. Conclusion ΓòÉΓòÉΓòÉ
Conclusion
The article demonstrated how a specialized device driver was used to assist a
user process in performing direct I/O. The final overhead, compared to a pure
device driver or a DOS program implementation, is just the CPU cycles of the
indirect intersegment call through the call gate and the return instruction.
Every other available method significantly adds a performance penalty. This
also holds for I/O in a DOS Box, which was not explained in this article. It
is to be expected, however, that this method will not be available any longer
in future Power PC systems, so avoid the demonstrated trick unless absolutely
necessary.
32-Bit I/O With Warp Speed - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 10.1. Introduction ΓòÉΓòÉΓòÉ
/dev/EDM2/BookReview
Written by Carsten Whimster
Introduction
In /dev/EDM2/BookReview, I focus on development books and materials. The
column is written from the point of view of an intermediate PM C programmer and
intermediate REXX programmer. Pick up whichever book strikes your fancy, and
join the growing group of people following our PM programming columns. I have
already reviewed a number of beginner's books, and will try to concentrate a
bit more on intermediate techniques and special topics from now on.
Please send me your comments and thoughts so that I can make this column as
good as possible. I read and respond to all mail.
Programming the OS/2 Warp GPI is the most up-to-date book specifically covering
the GPI, which I have reviewed yet.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.2. Errata ΓòÉΓòÉΓòÉ
Errata
My web page is finally coming of age, despite a minor accident. The OS/2
section has grown dramatically, and now has a large number of useful links to
other OS/2 sites. Check it out at
http://www.undergrad.math.uwaterloo.ca/~bcrwhims/.
My machine has been upgraded to an AMD DX4-100 with 20 Mb RAM and an ATI Mach64
with 2 Mb DRAM. Due to the increased speed and responsiveness, my interest in
developing is growing once again. I am working on an update to my POV-Panel/2,
and also on a couple of other projects, including a POV-Ray editor, and a PM
version of an old video game called Qix. We'll see how far I get with all of it
though <grin>.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.3. Programming the OS/2 Warp GPI ΓòÉΓòÉΓòÉ
Programming the OS/2 Warp GPI
For a while now, the OS/2 world has been without an in-depth, up-to-date book
on the GPI. Now things are about to change, both because of this book, and
also because Graham Winn's book has been updated as well. Here are the chapter
headings for this, the newest of Stephen Knight's and Jeffrey Ryan's OS/2
books:
Overview
OS/2 Architecture
Graphic Primitives
Fonts
Building Blocks of the GPI
Transformations
Paths, Regions, Clipping, Boundary Accumulation, and Correlation
Printing Graphics
OS/2 Metafiles
Appendix A: GPI Functions
Appendix B: Working with the Diskette
This is a book by the author of Learning to Program OS/2 2.0 Presentation
Manager by Example, and it shows. I criticized that particular book for only
including a single, monolithic program as the example the whole book was built
around. This book has the same basic structure, but I won't reiterate my
criticism unless I feel that this book also suffers from the same faults that
I described in the first one.
Reading this book quickly showed that the authors' ability to explain
difficult material has not decreased with time. The writing is lucid, and
more in-depth than the first book. This book is quite unusual in that it
presents a complete, well-featured program in good detail throughout the
chapters. The Overview presents the graphics application from the user's
perspective, and really is a user manual, albeit a little short.
The next chapter, inexplicably called OS/2 Architecture, spends most of its
time explaining the architecture of the GPI, and the OS/2 graphics viewing
pipeline. The GPI architecture is quite complicated, and not really intuitive
at all, but when you spend some time reading up on it, a lot of it come
together. I still wonder if there isn't a better way to do things, though. It
really does seem needlessly complicated to me. Hopefully DIVE will give those
of us who prefer building things more manually a much-needed reprieve from the
GPI. Anyway, enough complaining about the GPI!
The third chapter discusses graphic primitives like lines, circles, ovals,
rectangles, as well as graphic attributes like line width, line colour,
character colour, character shear, image colour, marker mix, and so on ad
infinitum. There really are an absolutely astounding number of attributes to
worry about, but they can be grouped into logical subsets, of course. These
subsets are then explained briefly, followed by explanations of the line and
arc primitives, including line join options. Some of the specific line
options are outlined, but the main philosophy of the book is to explain only
the most common functions in detail. Others may or may not get mentioned, but
you can rest assured that 90-95% of what you will use is here. Some of the
fills are also explained here, including the functions that use them. Also in
this chapter is an introduction to text primitives, or in other words, using
fonts in graphics. Finally, we are treated to an introduction to bitmap
usage.
Chapter four is the first non-introductory chapter on any subject so far, and
it attacks fonts. By the way, if you look at the chapter headings of this
book, and compare them to the chapter headings of Winn's book, you will see a
remarkable similarity there. I suppose it is unavoidable to a certain extent,
but it doesn't look like a complete coincidence. Indeed, Graham Winn is given
credit in the Acknowledgements section, so it looks like there is a fairly
close relationship between the various graphics-book authors working at IBM.
It should be interesting to see what Winn's new book will look like. In any
case, back to the Fonts chapter. This chapter, like the rest, has an
introductory paragraph giving a little background to the subject. I prefer to
see a little more, and to have it also give a quick preview of what the
chapter contains so that you know where you are headed, but that could be just
personal preference. After the introductory paragraph, we are told a bit
about codepages. This is interesting material, but at the same time, I really
wish it didn't have to be there, ie. IBM should take some initiative with
OS/2, and move towards double-byte characters, so that we won't have to deal
with codepages any more. Yes, this would slow down our systems a bit, but I
think that in the long run, it is worth it. But, back to our book. Outline
fonts, image (bitmapped) fonts, kerning, font metrics, font attributes, and
width tables are all introduced, and explained, and some larger code snippets
out of the sample application are given.
The fifth chapter launches into an explanation of the building blocks that the
GPI is constructed from, such as graphics orders and elements. Segments are
covered in good depth, and then the graphics viewer is introduced into our
subject matter. Quite a bit of code is given along the way, in large-ish
chunks. Sometimes it is a little hard to grasp everything, with so much
listed at a time.
The next chapter deals with the various transformations that the GPI allows
you to perform on objects, including revisiting the coordinate spaces. You
generally draw your objects first, and then put them through the
transformations on the way to their final form. A fair amount of matrix math
is needed to do this, so be sure that you are up on this subject before
attempting to read this chapter. Of course, the GPI does supply the tools to
do this, but comprehension is important.
Paths, regions, and so on is chapter seven's subject. It deals with the
possibility of creating paths and regions, and then using these to either
clip, fill, or otherwise modify various (other) objects. This is a fairly
powerful technique, which you will most likely find a need for if you get into
GPI in any depth at all. There are various ways to define paths and regions,
and ways of combining them. Redrawing using regions is also explained. Model
space clipping, page space clipping, device space clipping, and other clipping
related options are all sub-sections of this chapter. In addition to these,
there is a section called correlation, which is a bit of a god-send to anyone
trying to design something like a Doom editor. This subject deals with the
GPI's ability to select objects based on mouse- clicks and keystrokes. To
this end, tags are explained here. They are used with objects to yield the
desired granularity for the selection operation. A medium-sized code snippet
goes along with this, but my feeling is that some more depth would have been
nice here.
Printing graphics is the next chapter, and it explains the device independence
of OS/2's printing sub-system, as well as a basic outline of the
graphics-printing relationship in OS/2. Chapter 9 delves into OS/2's
metafiles, and the raison-d'etre for this otherwise fairly unused format.
Basically, it is meant as a go-along to the GPI, and is supposed to be used
for picture interchange between applications of different nature. It saves
more information than the other non-native format of the drawing editor, TIFF,
in that drawing commands themselves can be stored in a metafile. It is in
some ways more similar to a printer or the screen, than to other graphics
formats, in that it is handled as a device under OS/2. Again, a large- ish
chunk of code is regurgitated at the end of the chapter, making the reading a
little heavier than usual. With these large code-snippets, it is harder to
dissect what is necessary, and what is frills. Still, a good deal more can
potentially be taught as opposed to small programs that do little.
The appendices have information on the GPI functions (basically a
quick-reference listing of the GPI functions of Warp), and a small section on
how to use the accompanying diskette.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.4. Summary ΓòÉΓòÉΓòÉ
Summary
I like this book a fair amount, and it is a definite improvement on the feel of
Stephen Knight's Learning to Program OS/2 2.0 Presentation Manager by Example.
At the same time, having only a single sample program has to have its
limitations, and I can't help but feel that certain areas could have been
covered more in depth. This does not in any way mean that this book is not a
good book, and in fact, one might equally well complain that most books, by
having a large number of small programs miss out on the chance to treat certain
other subjects in depth. It is more of a new angle than a bad angle. I
personally prefer more small programs, but I won't let this affect my judgement
of the book, because not everyone feels the same way. I feel that sometimes
the reader is left for a long time without concrete code to browse, and other
times the code snippets get a little large to digest. For this reason only, I
give this book an A-, rather than an A.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.5. Book Reviewed ΓòÉΓòÉΓòÉ
Book Reviewed
Programming the OS/2 Warp GPI, Knight and Ryan.
- Wiley and Sons. ISBN 0-471-10718-2. US$39.95, CAN$55.95.
- OS/2 Graphics Programmers
- A-
This book should be extremely attractive to anyone writing a graphics
editor, since it includes a capable, if not full-featured graphics editor
program and full source. It may appeal less to games writers and other
graphics programmers due to the limited nature of using only one sample
application. Very readable, and well-explained, however.
NOTES
Please note that books aimed at different audiences should only be compared
with great care, if at all. I intend to concentrate on the strong points of
the books I review, but I will point out any weaknesses in a constructive
manner.
LEGEND
BOOK: The name of the book, and the author(s)
PUBLISHING INFORMATION: Publishing company, ISBN, and approximate price.
AUDIENCE: This is a description of the audience I think the book targets
best. This is not intended as gospel, just a guideline for people not
familiar with the book.
MARK: My opinion of the success of the book's presentation, and how well it
targets its audience. Technical content, accuracy, organization, readability,
and quality of index all weigh heavily here, but the single most important
item is how well the book covers what it says it covers. Many books try to
cover too much, and get a lower mark as a result.
A+ Ground-breaking, all-around outstanding book.
A Excellent book. This is what I want to see happen a lot.
A- Excellent book with minor flaws.
B+ Very good book with minor flaws or omissions.
B Good book with some flaws and omissions.
B- Good book, but in need of improvement.
C+ Mediocre book with some potential, but in need of some updating.
C Mediocre book with some good sections, but badly in need of fixing.
C- Mediocre book, little good material, desperately in need of an
overhaul.
D Don't buy this book unless you need it, and nothing else exists.
F Don't buy this book. Period.
COMMENTS: This is a very brief summary of the review proper.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.6. Index ΓòÉΓòÉΓòÉ
Index
This Content Index is designed to let you find the book that covers the topics
you need to learn about. It will eventually have a lot of categories, with
each book being rated along each row. These tables will be quite large, and
will continually grow, so please give me your feedback regarding what
categories you would like to see, and which you don't. It may take me a while
to flesh them out, so have a little patience.
BOOK LEGEND
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéCode ΓöéIssue ΓöéTitle Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRWP Γöé2-3 ΓöéReal World Programming for OS/2 2.1 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéLPE Γöé2-4 ΓöéLearning to Program OS/2 2.0 Presentation Manager by Example Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéODD Γöé2-5 ΓöéWriting OS/2 2.1 Device Drivers in C Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéGPI Γöé2-6 ΓöéOS/2 Presentation Manager GPI Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéTAO Γöé2-7 ΓöéThe Art of OS/2 2.1 C Programming Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéMOR Γöé2-8 ΓöéMastering OS/2 REXX Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRSH Γöé2-9 ΓöéREXX Reference Summary Handbook Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéADO Γöé2-10 ΓöéApplication Development Using OS/2 REXX Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPMP Γöé2-11 ΓöéOS/2 Presentation Manager Programming Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéDOA Γöé3-1 ΓöéDesigning OS/2 Applications Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOSP Γöé3-2 ΓöéOS/2 Programming Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéTGO Γöé3-4 ΓöéThe GUI-OOUI War Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOU Γöé3-5 ΓöéOS/2 Warp Unleashed, Deluxe Edition Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéQR1 Γöé3-6 ΓöéWIN Functions, OS/2 Quick Reference Library Volume 1 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPWG Γöé3-7 ΓöéProgramming the OS/2 Warp Version 3 GPI Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
NOTE: Books which cover the same material can look similar in this table, but
be different in real life. The style of a book, for example, can not be seen
from a quick table, so make sure that you follow up by reading the reviews of
the books you find here. Finally, be sure that the books you are comparing are
aimed at the same audiences.
PM C BOOKS
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM ΓöéGPI ΓöéFonts ΓöéPrint Γöé
Γöé Γöé ΓöéBasics ΓöéDriver ΓöéAVIO ΓöéIntro Γöé Γöé Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRWP ΓöéB+ Γöé2 Γöé0 Γöé0 Γöé4 Γöé4 Γöé4 Γöé3 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPME ΓöéB- Γöé1 Γöé0 Γöé0 Γöé2 Γöé2 Γöé2 Γöé0 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéODD ΓöéA Γöé0 Γöé5 Γöé0 Γöé0 Γöé1 Γöé0 Γöé1 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéGPI ΓöéC+ Γöé0 Γöé0 Γöé0 Γöé0 Γöé5 Γöé2 Γöé3 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéTAO ΓöéB+ Γöé3 Γöé2 Γöé1 Γöé4 Γöé1 Γöé2 Γöé0 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPMP ΓöéA- Γöé1 Γöé0 Γöé1 Γöé5 Γöé3 Γöé4 Γöé2 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOSP ΓöéB+ Γöé2 Γöé0 Γöé0 Γöé3 Γöé2 Γöé1 Γöé0 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéQR1 ΓöéA Γöé0 Γöé0 Γöé0 Γöé(WIN) 5Γöé0 Γöé0 Γöé0 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéPWG ΓöéA- Γöé0 Γöé0 Γöé0 Γöé1 Γöé5 Γöé5 Γöé5 Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
REXX BOOKS:
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéBOOK ΓöéMARK ΓöéREXX ΓöéWPS ΓöéReferenceΓöé
Γöé Γöé ΓöéIntro Γöé Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéMOR ΓöéB Γöé4 Γöé0 Γöé2 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéRSH ΓöéA Γöé1 Γöé2 Γöé5 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéADO ΓöéA- Γöé3 Γöé2 Γöé4 Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
SYSTEM AND NON-PROGRAMMING BOOKS:
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
ΓöéBOOK ΓöéMARK ΓöéKernel ΓöéDevice ΓöéVIO andΓöéPM ΓöéThread ΓöéGPI ΓöéFonts ΓöéPrint ΓöéWPS Γöé
Γöé Γöé ΓöéBasics ΓöéDriver ΓöéAVIO Γöé Γöé Γöé Γöé Γöé Γöé Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéDOA ΓöéA Γöé4 Γöé4 Γöé2 Γöé4 Γöé5 Γöé3 Γöé2 Γöé3 Γöé0 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéTGO ΓöéB Γöé0 Γöé0 Γöé0 Γöé2 Γöé1 Γöé0 Γöé2 Γöé1 Γöé5 Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
ΓöéOU ΓöéA+ Γöé1 Γöé4 Γöé4 Γöé5 Γöé2 Γöé5 Γöé5 Γöé5 Γöé5 Γöé
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
RATINGS LEGEND:
ΓöîΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé0ΓöéNo coverage Γöé
Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé1ΓöéVery light coverage Γöé
Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé2ΓöéIntroductory coverage Γöé
Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé3ΓöéGood Coverage Γöé
Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé4ΓöéIn-depth coverage Γöé
Γö£ΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
Γöé5ΓöéAuthoritative Γöé
ΓööΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 10.7. Coming Up ΓòÉΓòÉΓòÉ
Coming Up
I am expecting Reich's new book for next month, but we'll see if it gets here
in time. The following are some other books I intend to review, in no
particular order:
Designing High Powered OS/2 Applications, Reich
OS/2 Presentation Manager GPI, 2nd edition, Winn
The Design of OS/2, 2nd Edition, Kogan and Deitel
If anyone has a book they want to see reviewed, I will be happy to oblige.
Just mail me and tell me. Publishers can send me books at the address on my
personal page at the end of the magazine, and I will review all OS/2
development- related and advanced user books I receive.
/dev/EDM2/BookReview - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 11. OOPS Avenue ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 11.1. Introduction ΓòÉΓòÉΓòÉ
OOPS Avenue
Written by Gordon Zeglinski
Introduction
There is a new C++ library out called STL (Standardized Template Library). As
the name implies, the library is being standardized and consists of template
classes and functions. There are a couple of versions of STL available. The
easiest (and cheapest) one to get is the HP source code available from
butler.hpl.external.hp.com in the /stl directory.
So now that you know where to get it, let's take a brief look at it.
OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 11.2. What Is STL? ΓòÉΓòÉΓòÉ
What Is STL?
STL is a set of template functions and classes that provide a portable compiler
neutral toolkit for manipulating and storing data. Roughly speaking, STL does
for "container objects" what the IOSTREAM library does for I/O. The two
implementations of STL that I've looked at were not header file compatible.
Thus, one should consider STL still in its infancy.
The design of STL is very different from most other container type object
classes. While most use templates, they also use inheritance and virtual
functions. This both affects the performance and the ability to share the
object across processes. Virtual functions are usually implemented as lookup
tables attached to the object's instance; when a virtual function is called,
its address is pulled from the lookup table. This address is then used to call
the appropriate member function. If, for example, an instance of an object is
created in shared memory, and this object has virtual functions, the lookup
table would be filled with addresses of functions belonging to the process that
created the instance. This of course means that only the process creating this
instance can use this instance. Because STL doesn't use virtual functions,
this limitation is not present.
Another interesting point about the design of STL is that functions to sort,
search or otherwise manipulate data are not member functions of the container
classes. This allows the same functions to operate on C-style arrays and C++
based container classes. The class can be divided into 5 primary components:
algorithms, containers, iterators, function objects and adaptors. Algorithms
perform actions such as sorting, searching, merging and the like. Containers
manipulate groups of objects and the memory they require. Iterators are used
to move through a container. Function objects encapsulate functions use by
other parts of the library. Adaptors provide an alternative interface to a
component of the library.
OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 11.3. A Simple Program ΓòÉΓòÉΓòÉ
A Simple Program
Let's look at a simple simple test program using standard C-style arrays. The
following sample is a modified version of the sort_example.cpp program. The
program was modified to work with C-Set++. Also note that the STL header file
algobase.h had the definitions for min and max commented out to prevent
conflict with the min and max macros defined in C-Set++.
#include "defalloc.h"
#include "algo.h"
#include "tempbuf.cpp" // Can also just compile and link with this file
#include "heap.h"
#include "function.h"
#include "random.cpp" // Can also just compile and link with this file
//Rand is used to fill the array with sequential numbers
class Rand{
int I;
public:
Rand(unsigned long X):I(X){}
int operator()(){return I++;}
};
void main(int argc, char *argv[]){
int *last1;
int *middle;
int test_sequence1[15];
middle = test_sequence1 + 10;
last1 = test_sequence1 + 15;
ostream_iterator<int> out_stream(cout, " ");
less<int> less_than;
generate((int*)test_sequence1, last1, Rand(0));
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
sort((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
sort((int*)test_sequence1, last1, less_than);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
stable_sort((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
stable_sort((int*)test_sequence1, last1, less_than);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle((int*)test_sequence1, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
partial_sort((int*)test_sequence1, middle, last1);
copy((int*)test_sequence1, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 1? 1? 1? 1? 1?
}
In the above example, last1 and middle are iterators. The array
test_sequence1[15] is the container.
Basically, the sample involves filling the container, shuffling the elements
and then sorting them using the various sort algorithms. Similarly, one can
use a vector container. A vector container is the closest thing to a C array.
The follow example uses a vector instead of an array.
#include "defalloc.h"
#include "algo.h"
#include "tempbuf.cpp" // Can also just compile and link with this file
#include "heap.h"
#include "function.h"
#include "vector.h"
#include "random.cpp" // Can also just compile and link with this file
//Rand is used to fill the array with sequential numbers
class Rand{
int I;
public:
Rand(unsigned long X):I(X){}
int operator()(){return I++;}
};
void main(int argc, char *argv[]){
vector<int>::iterator Start;
vector<int>::iterator last1;
vector<int>::iterator middle;
vector<int> test_sequence1(15);
ostream_iterator<int> out_stream(cout, " ");
less<int> less_than;
Start=test_sequence1.begin();
last1 = Start + 15;
generate(Start, last1, Rand(0));
Start=test_sequence1.begin();
middle = Start + 10;
last1 = Start + 15;
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
sort(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
sort(Start, last1, less_than);
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
stable_sort(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
stable_sort(Start, last1, less_than);
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
random_shuffle(Start, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: (the sequence of 0 through 14 with elements in random order)
partial_sort(Start, middle, last1);
copy(Start, last1, out_stream), cout << endl;
// Output: 0 1 2 3 4 5 6 7 8 9 1? 1? 1? 1? 1?
}
As before, last1 and middle are iterators. The container is test_sequence1.
However, a new iterator called Start is introduced. In the first example, the
container could double as the starting iterator because the container was
simply a pointer. In the second sample, the container is a vector class. The
vector class can't act as an iterator so we use Start. In our last example, we
will use the set manipulation functions to create a vector based upon 2 other
vectors.
typedef vector<int> IVec;
void main(int argc, char *argv[]){
vector<int> Set1,Set2,Output;
ostream_iterator<int> out_stream(cout, " ");
less<int> less_than;
//let's insert some values at the END
// of the vector
Set1.insert(Set1.end(),10);
Set1.insert(Set1.end(),11);
Set1.insert(Set1.end(),2);
Set1.insert(Set1.end(),1);
Set1.insert(Set1.end(),12);
Set1.insert(Set1.end(),5);
Set2.insert(Set2.end(),10);
Set2.insert(Set2.end(),5);
Set2.insert(Set2.end(),2);
Set2.insert(Set2.end(),20);
Set2.insert(Set2.end(),24);
//let's display our two vectors
cout<<"Set 1"<<endl;
copy(Set1.begin(),Set1.end(), out_stream), cout << endl;
cout<<"Set 2"<<endl;
copy(Set2.begin(),Set2.end(), out_stream), cout << endl;
//set operations work on sorted containers.. sooo
//let's sort these puppies and then display them..
sort(Set1.begin(),Set1.end());
cout<<"Set 1 Sorted"<<endl;
copy(Set1.begin(),Set1.end(), out_stream), cout << endl;
sort(Set2.begin(),Set2.end());
cout<<"Set 2 Sorted"<<endl;
copy(Set2.begin(),Set2.end(), out_stream), cout << endl;
//let's get the union and put it in the Output vector
set_union(Set1.begin(),
Set1.end(),
Set2.begin(),
Set2.end(),
insert_iterator<IVec>(Output,Output.begin()));
cout<<"Union"<<endl;
//display the output vector
copy(Output.begin(),Output.end(), out_stream), cout << endl;
//display the result
Output.erase(Output.begin(), Output.end());
//get the intersection
set_intersection(Set1.begin(),
Set1.end(),
Set2.begin(),
Set2.end(),
insert_iterator<IVec>(Output,Output.begin()));
cout<<"Intersection"<<endl;
copy(Output.begin(),Output.end(), out_stream), cout << endl;
Output.erase(Output.begin(), Output.end());
//lets find the difference between set1 and set2
set_difference(Set1.begin(),
Set1.end(),
Set2.begin(),
Set2.end (),
insert_iterator<IVec>(Output,Output.begin()));
cout<<"Difference Set1 <-> Set2"<<endl;
copy(Output.begin(),Output.end(), out_stream), cout << endl;
Output.erase(Output.begin(), Output.end());
//lets find the difference between set2 and set1
set_difference(Set2.begin(),
Set2.end(),
Set1.begin(),
Set1.end (),
insert_iterator<IVec>(Output,Output.begin()));
cout<<"Difference Set2 <-> Set1"<<endl;
copy(Output.begin(),Output.end(), out_stream), cout << endl;
}
An interesting point worth noting is that the set_* functions use iterators to
determine where the results of the set operations go. There's no reason the
output couldn't have been sent directly to the display instead of to the Output
vector. This is left as an exercise for the curious.
OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 11.4. Wrapping Things Up ΓòÉΓòÉΓòÉ
Wrapping Things Up
Well that's about it for our quick look at STL. The files arraysort.cpp,
vecsort.cpp and vecunion.cpp are included if you wish to try and compile the
sample programs. Note the HP STL release may not compile on your particular
C++ compiler. It requires a very accurate template implementation to work.
Coming up in future issues, we'll be looking at various OS/2 C++ compilers.
We'll be using STL as part of our compiler testing.
OOPS Avenue - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 12. Contributors to this Issue ΓòÉΓòÉΓòÉ
Are You a Potential Author?
We are always looking for (new) authors. If you have a topic about which you
would like to write, send a brief description of the topic electronically to
any of the editors, whose addresses are listed below, by the 15th of the month
before the month in which your article will appear. This alerts us that you
will be sending an article so that we can plan the issue layout accordingly.
After you have done this, get the latest copy of the Article Submission
Guidelines from hobbes.nmsu.edu in the /os2/newsltr directory. (The file is
artsub.zip.) The completed text of your article should be sent to us no later
than five days prior to the last day of the month; any articles received after
that time may be pushed to the next issue.
The editors can be reached at the following email addresses:
Larry Salomon - os2man@panix.com (Internet).
Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet).
The following people contributed to this issue in one form or another (in
alphabetical order):
Mike Duffy
Juergen Riedl
Larry Salomon, Jr.
Holger Veit
Carsten Whimster
Gordon Zeglinski
Network distributors
Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 12.1. Michael T. Duffy ΓòÉΓòÉΓòÉ
Michael T. Duffy
Michael is a recent graduate of the University of Southern California and has
degrees in Cinema Production and East Asian Languages and Cultures. His
computer skills are self-taught, and he has been programming for OS/2 since
about December of 1994. Michael is working on breaking into the game
development industry, and has been working towards that goal for a number of
months. He expects to release his first game, an OS/2 shooter, later this
year.
Michael can be reached on the internet at mduffy@ionet.net.
ΓòÉΓòÉΓòÉ 12.2. Juergen Riedl ΓòÉΓòÉΓòÉ
Juergen Riedl
Juergen Riedl is physicist and has studied at the Ludwig Maximilians University
of Munich / Germany / Bavaria. He is a system engineer at Siemens Nixdorf
Informationsystems and currently working on information models for SDH high
bandwidth management systems. All programming is self- taught; he has been
programming OS/2 applications since the release of OS/2 2.0. When he is not
doing OS/2 he can be found in summer in the Alps sailplaning or in the winter
rigging up his model railway.
Juergen can be reached at j.riedl@mch.sni.de.
ΓòÉΓòÉΓòÉ 12.3. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
Larry Salomon Jr.
Larry Salomon Jr. has been developing OS/2 applications since version 1.1 in
1989. He has written numerous applications, including the Scramble applet that
was included in OS/2 versions 2.0-2.11, and the I-Brow, Magnify, and Screen
Capture trio that has been distributed on numerous CD-ROMs.
Larry is also the coauthor of the successful book, The Art of OS/2 2.1 C
Programming (Wiley-QED). Finally, he is the CEO/President of IQPac Inc. which
is responsible for the publication of EDM/2 and he is a frequent contributor to
the publication.
Larry can be reached electronically via the Internet at os2man@panix.com.
Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 12.4. Holger Veit ΓòÉΓòÉΓòÉ
Holger Veit
Holger Veit studied electrical engineering and also holds a PhD degree in this
area (testing of digital circuits). He is currently working as a senior
researcher at the GMD (German National Research Center for Information
Technology) where he is developing CAD methodologies for designing mixed
hardware and software systems. His interest in OS/2 is almost a private
pleasure, but he has several years of detailed experience (down to the
motherboard level) with operating systems like BSD and OS/2.
He can be reached via e-mail at holger.veit@gmd.de.
ΓòÉΓòÉΓòÉ 12.5. Carsten Whimster ΓòÉΓòÉΓòÉ
Carsten Whimster
Carsten is an undergraduate Computer Science student at the University of
Waterloo. He is currently in fourth year, and enjoying it immensely. He uses
Watcom C/C++ 10.0a and Watcom VX-REXX 2.0b. Carsten is the author of some
commandline utilities, and POV-Panel/2. He is currently trying to learn enough
GPI programming to do a remake of the old video game Qix. He is also a
TEAM-OS/2 member, and has adopted a little computer store called The Data Store
in Waterloo, Ontario, which promptly hired him part-time.
You may reach Carsten...
...via email:
bcrwhims@undergrad.math.uwaterloo.ca - Internet
...World Wide Web homepage (incomplete; aren't they all):
http://www.undergrad.math.uwaterloo.ca/~bcrwhims - WWW
...via snail mail:
Carsten Whimster
318A Spruce Street
Waterloo, Ontario
Canada
N2L 3M7
...via phone
(519) 886-2439
Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 12.6. Gordon Zeglinski ΓòÉΓòÉΓòÉ
Gordon Zeglinski
Gordon Zeglinski is a freelance programmer/consultant who received his Master's
degree in Mechanical Engineering with a thesis on C++ sparse matrix objects.
He has been programming in C++ for 6 years and also has a strong background in
FORTRAN. He started developing OS/2 applications with version 2.0 .
His current projects include a client/server communications program that
utilitizes OS/2's features which has entered beta testing. Additionally, he is
involved in the development of a "real-time" automated vehicle based on OS/2
and using C++ in which he does device driver development and designs the
applications that comprise the control logic and user interface.
He can be reached via the Internet at zeglins@cc.umanitoba.ca.
Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7
ΓòÉΓòÉΓòÉ 12.7. Network distributors ΓòÉΓòÉΓòÉ
Network Distributors
These people are part of our distribution system to provide EDM/2 on networks
other than the Internet. Their help to provide access to this magazine for
others is voluntary and we appreciate them a lot!
Paul Hethmon (phethmon@utk.edu) - Compuserve
Gess Shankar (gess@knex.mind.org) - Internet
Jason B. Tiller (PeerGynt@aol.com) - America On-line
David Singer (singer@almaden.ibm.com) - IBM Internal
Jesper Nielsen (afdata@pop02.ny.us.ibm.net) - Denmark BBS's
If you would like to become a "network distributor", be sure to contact the
editors so that we can give you the credit you deserve!
Contributors - EDM/2 - Aug 1995 - Volume 3, Issue 7