home *** CD-ROM | disk | FTP | other *** search
-
- ΓòÉΓòÉΓòÉ 1. Sept 1994 Title Page ΓòÉΓòÉΓòÉ
-
- EDM/2
-
- The Electronic Developer's Magazine for OS/2
-
- Portions copyright (c) by Larry Salomon Jr.
- Volume 2, issue 8
-
- Copyright Notice and Other Stuff
-
- The Editor-in-Chief of this electronic magazine is Larry Salomon, Jr.
-
- Portions of EDM/2 are copyrighted by the editors. 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.
-
- All articles are copyrighted by their authors. No part of any article may be
- reproduced without permission from the original author.
-
- Neither this publication nor the editors 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.
-
- Administrivia
-
- Oh boy!
-
- What a time it has been. One never realizes how much a job can take out of you
- until you have a two month break from it. If you only knew how hard I had to
- kick myself to get back into the routine. <grin> So much has happened, and I
- am the worst note-taker in the world; still, I will try my best to tell you all
- about it here.
-
- Internet Relay Chat
-
- Some time ago, I mentioned how addicting this can become. It should be noted,
- however, that there exists a channel called #os/2 where many people frequent;
- if you have any questions and are lucky enough to have access to this, you
- might want to drop by. Given the popularity of this chatting program, an idea
- has been considered where seminars could be given on a channel on programming
- techniques. We will keep you posted.
-
- VIO and the PM Subset
-
- This month sees the beginning of a new series on the development of a library;
- what makes this library so special is that it is a subset of PM for full-screen
- character-mode applications. The library was written for a project at work
- (which should be on the market soon), but you'll get to see it in depth (along
- with source code, of course) right here.
-
- Sprites Revisited
-
- If you will remember back to the sprite series, I mentioned that the code was
- written with the idea that z-ordering could be added easily at a later date.
- Since then, I have had a some free time on my hands (though not much), so I
- added this useful capability. The necessary changes are discussed as well as
- the two new APIs that deal with layering in an update to that well-received
- series.
-
- A Helper for the Needy
-
- Have you ever called a function in an application, only to get the "undefined
- prototype" message when you called it? Antonio "Tony" Tonizzo has gotten that
- message one too many times, and he finally decided to do something about it.
- The result is included with this issue (see API.ZIP); it has the #define
- constant that needs to be defined for each API in OS/2. Good work, Tony!
-
- For the Short-Sighted
-
- If you hang out in comp.os.os2.programmer.misc, you've probably noticed Dick
- Conklin (the editor of OS/2 Developer) making a post every now and then. I
- find it exciting that the net is receiving more attention from the media, even
- if it has taken them a long time to do so.
-
- That's it for this month! Enjoy the issue!
-
- Title Page - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2. WPS Programming the Easy Way - Part 1 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 2.1. Introduction ΓòÉΓòÉΓòÉ
-
- WPS Programming the Easy Way - Part 1
-
- Written by Frank Matthijs
-
- Introduction
-
- This is the first of two articles about WPS programming. As this is an
- introduction, you don't have to know anything at all about WPS programming in
- order to follow the articles. In fact, they may be too basic for some of you.
- But if you always wondered why all those things on your desktop are called
- objects, and how you are supposed to make your own objects, read on.
-
- After reading these articles, you'll be able to explore the WPS on your own, so
- you can start making your own objects. You can follow the articles with your
- compiler ready, so you can actually make the objects described in the articles
- and see for yourself how it all works.
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.2. Overview ΓòÉΓòÉΓòÉ
-
- Overview
-
- Welcome to the magical world of WPS programming. Since this is a relatively
- new area of programming, there are very few sources of information for
- beginning WPS programmers to find the info they need. Of course, there are the
- PM Reference and SOM Reference documents, but a reference is only useful when
- you already know something about the subject, or else it rapidly becomes an
- overwhelming collection of unknown terms.
-
- Another source are the numerous sample WPS objects in the IBM toolkit (er,
- actually there is only one, the Car class). It is very interesting to study
- this example, but unfortunately, it contains a few nasty bugs so that some
- features only nearly work. Furthermore, it is somewhat difficult to grasp the
- underlying principles just by studying a "working" example.
-
- That's why you're now reading the first of a two-part series on WPS
- programming. They are intended for as many programmers as possible. Therefore,
- a few very basic concepts are briefly explained (as far as they relate to WPS
- programming), such as inheritance. Experienced WPS programmers will not find
- these articles of any use, but they could have already guessed so from the
- title of the series.
-
- What You Will Find
-
- This first article will explain some basic concepts of WPS programming. Topics
- covered include object oriented programming (classes, objects, inheritance) and
- SOM programming (class definition file, creating the class DLL, registering the
- DLL). After that follows a first introduction to the practice of WPS
- programming. We will build a new (very basic) WPS object, step by step.
-
- In the second article our object will be extended to make it more useful, and
- especially to demonstrate how to use some of the methods and what they're for.
- Our object will offer only part of the functionality of the Car example, but
- the things that are broken there will work here. Because the articles are
- intended to be a starting point for your own explorations in WPS land, you'll
- be able to add your own functions easily.
-
- After reading the articles and following the examples, you should be able to
- understand most of the explanations in the PM/WPS and SOM references, although
- the descriptions are sometimes too vague or inaccurate to be of any help. I
- hope there will eventually be enough WPS programmers around to get some
- interesting discussions going in one of the electronic conference areas or
- mailing lists.
-
- What You Will Need
-
- In order to be able to actively follow the programming examples in the articles
- and to get into WPS programming yourself, you need the SOM compiler. As far as
- I know, this is a problem for programmers using Borland C++ or the GNU GCC or
- EMX development tools. That is probably the only obstacle on your way to
- becoming a proficient WPS programmer, but it is of course a very serious one.
- I'm afraid you won't be able to enjoy WPS programming if you use one of these
- tools, since I know of no public domain SOM compiler. Perhaps if you bother
- Borland enough, they'll license the SOM compiler from IBM?
-
- If you're still with us, fine. You'll also find the SOM reference and the part
- of the PM reference about the Workplace Shell useful, though not as useful as
- it could have been due to vague or incomplete descriptions (but we're used to
- that, aren't we?).
-
- In the examples, I'll assume you use C-Set/2 or C-Set++. If you use another
- compiler, you may have to modify the makefile, and you should substitute your
- own make program for NMAKE.
-
- What You Need to Know
-
- Since this is an introduction to WPS programming, you don't need to know
- anything about it before you start. Of course, since the WPS uses the
- Presentation Manager API a lot, it doesn't hurt if you are at least somewhat
- familiar with PM programming. In these introductory articles, I will stress
- basic WPS stuff, so you don't need to be a PM expert to be able to understand
- what is said.
-
- Because the WPS is based on SOM, and the "O" in "SOM" means "Object", some
- knowledge of object related topics will be a real plus, but I'll try to explain
- the most relevant items in what follows, in case you have never heard of
- objects before (mmm, where have you been the last couple of years, then?).
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.3. Object oriented programming ΓòÉΓòÉΓòÉ
-
- Object oriented programming
-
- [OO experts, please note: the following explanation is oversimplified and may
- even be inaccurate. Its purpose is only to give programmers who know
- absolutely nothing about OO programming enough information to get them started
- with SOM and WPS. OK?]
-
- In this section, I'll explain some terms and concepts related to OO
- programming. There's nothing exceptionally spectacular about it, but you'll
- have to know it if you want to fully understand what follows.
-
- Object
-
- An object is nothing more than a collection of data and code. The code is a
- collection of routines, usually called methods. A linked list for example can
- be an object. The data could consist of two pointers (start and end of the
- list) and a count of the elements in the list. Some methods would be provided
- for adding and removing elements to the list, and for determining the number of
- elements in the list.
-
- Good practice dictates that the data be kept private, i.e. unavailable to other
- objects. If this data must be queryable, you should provide methods to do so.
- This way, you can prevent other objects from tampering with the internal
- representation of your object. Moreover, if you later decide to change the
- internal workings of your object, you can do so without any problems, provided
- the external specification remains the same. This separation of the object
- interface from the implementation is a very big advantage of OO programming.
-
- For example: if you make a List, you could specify the methods Add, Remove,
- and QuerySize. The set of all methods, together with a specification of how to
- use them, forms the interface of your List. Everyone using a List must use
- QuerySize to get the number of elements in the List, Add to add an element to
- the List, and so on. You can change and improve the actual implementation of
- your List (for example, using pointers instead of an array) without this
- affecting its use. In other words: we can hide the actual implementation
- through the use of abstraction.
-
- Class
-
- Consider the concept Cat. You can say a lot of general things about Cat, for
- example it is an animal, has four legs and it purrs. These general features
- actually describe a whole class of animals: the class Cat. The cat of the
- neighbors and the one on your lap are specific instances of the class Cat.
-
- This may sound a little artificial when applied to cats, but these terms are
- also used in OO programming. A class is a general description of a collection
- of very related objects. Each of those objects is an instance of that class.
-
- For example, the List in the previous section really is a class (the List
- class). Every real list is an instance of the List class.
-
- Inheritance
-
- Some classes are related: a Cat is an Animal, a Rectangle is a Shape, and so
- on. This "is a" relationship is very common and defines a whole hierarchy of
- classes. Inheritance is the mechanism that allows programmers to express this
- relationship in an object oriented environment.
-
- When some class A "is a" B (e.g. a Data File "is a" File), we can derive class
- A from class B. The result is that class A inherits all methods of class B.
- All you can do with an object of class B can also be done with an object of
- class A. Of course, it is still possible to define extra functionality for
- objects of class A, by adding methods to the inherited ones. If you derive A
- from B, B is called the parent and A the child.
-
- One of the reasons why inheritance is a powerful mechanism, is that you can
- reuse most of the code you wrote for B. Suppose B is an Editor class,
- implementing a simple text editor, and you want to write a programmable editor,
- you can do so by making a new class, say ProgrammableEditor, and deriving this
- class from Editor. That way, you inherit all methods from Editor, so you don't
- have to recode the basic editor stuff like moving the cursor and storing the
- text.
-
- Another interesting feature of inheritance is that, when A is derived from B,
- any function that expects an object of class B, can actually be passed
- instances of class A as well. So you could make a class List with method Add,
- accepting objects of class Link. The result is you cannot only add objects of
- class Link to your List, but also any object of a class derived from Link. This
- feature is called polymorphism: you can have a List containing objects of
- different types.
-
- Besides adding methods in a derived class, it is also possible to replace the
- functionality of some inherited methods. Doing so is called overriding these
- methods. When A overrides a method it would inherit from B, it is asking to
- call its own version of the method instead of B's version. Luckily, B's
- version is still available, so A can choose to do its job and then call B's
- version of the method. This is somewhat similar to chaining interrupt vectors
- in good old DOS.
-
- For example, if we have a class Rectangle, and we want to make a new class
- Square, we can derive Square from Rectangle, because a Square really is a
- (special sort of) Rectangle. If Rectangle has a method QueryDiagonal, Square
- inherits this method, so you can also query the diagonal of a Square. You
- could make use of some specific property of a Square in calculating the length
- of the diagonal (e.g. all sides have the same length), so it could be useful to
- override the method QueryDiagonal in Square and provide the optimized
- calculation instead of the old one. In this example, the old version of
- QueryDiagonal is not called.
-
- The way inheritance is implemented, depends on the object environment (or
- programming language). Most of the time, the methods are not actually
- duplicated in A, but instead B's methods are called with A's data (the code is
- identical, only the data differs), except for overridden methods. When you
- call a method A inherited from B, the system determines some way or another
- that A is derived from B, so it in fact calls B's method. If the method is
- overridden, A's version is called. What function should be called can be
- determined statically, at compile time, or dynamically, at run time (in C++ for
- example, it's done statically).
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.4. SOM programming ΓòÉΓòÉΓòÉ
-
- SOM programming
-
- SOM is an object model (System Object Model), meaning it supports all concepts
- introduced in the previous section (and a lot more too). It is built right into
- OS/2, so you can immediately take advantage of it (provided you have a SOM
- compiler, of course).
-
- In SOM, you can define classes and create instances of these classes (it
- wouldn't be of much use otherwise, would it?). Of course, you'll have to
- produce some code in order to create a class. So where do we put this code?
- This is where SOM programming differs from "normal" programming: instead of
- making an executable file (a program), in SOM you create classes. The code for
- these classes is contained in a DLL. Let's see how we can produce such a DLL
- (we'll be making one later on).
-
- 1. When you want to define a class in SOM, you make a text file describing the
- properties of your class. Such a text file should have the extension .CSC
- and is called the class definition file. You can specify the name of your
- new class, the class you want to derive from (in SOM, you always derive
- from some class, you can't create "root" classes), the methods you want to
- override and the methods you want to add. This is always the first step
- when creating classes for SOM.
-
- 2. After that, you use the SOM compiler to convert this .CSC file to a
- collection of source files (C, C++ or some other language; currently only C
- and C++ are supported, we'll assume C here). So now we have something to
- put our code in.
-
- 3. The .C file contains default implementations for the methods you have
- overridden or added. You can then alter the generated source file (by
- adding you own code). When you have coded the methods, you have something
- you can convert to a DLL file. Note: when you later have to change your
- .CSC file, you must recompile it into new source files, but the SOM
- compiler is smart enough not to overwrite the changes and additions you
- have made (i.e. it doesn't simply generate a new generic source file).
-
- 4. The last step in the process is informing OS/2 of your new class, so that
- it can be used system-wide ever after. This is accomplished by registering
- your DLL, using a REXX script or a Win API function. After sucessfully
- registering your class, you and everyone else can create instances of your
- class (again using a REXX script or a Win function) and use these instances
- (objects). There are also functions to deregister a class and to replace a
- class with another one.
-
- One important thing to know about SOM objects is that they're persistent. This
- means they continue to exist, even when you shutdown your system and reboot.
- For this to be possible, most objects must save their state and restore it
- afterwards (this can be done by writing the state to one of the OS/2 INI files
- or to extended attributes).
-
- Metaclasses
-
- In SOM, the class of an object is in fact itself an instance of another class,
- its metaclass. This metaclass can have methods, just like a normal class. The
- difference with normal, instance methods (which act upon one particular
- instance of the class) is that these class methods act upon the class itself,
- and thus upon all instances of the class. We'll encounter both types of
- methods in WPS programming.
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.5. WPS Programming ΓòÉΓòÉΓòÉ
-
- WPS Programming
-
- The Workplace Shell is nothing more than a collection of complex SOM classes
- that make very intensive use of the OS/2 API, especially the Presentation
- Manager API. That's why concepts like object, class, method, inheritance,
- overriding, etc. were explained in the previous sections: they're needed for
- WPS programming because WPS is based on SOM and SOM is object oriented.
-
- WPS provides us with a number of classes to work with, like WPFolder, defining
- (surprise!) a folder class. You can create instances of these classes (for
- example, folders) with a REXX script or a Win API function, as described in the
- section about SOM programming. The Workplace Shell also provides another way
- to make instances of classes: the Templates folder. Dragging the Folder
- template, for example, actually creates an instance of the class WPFolder.
-
- You can see what classes WPS defines in the PM reference (under the heading
- Workplace). All objects you see on your desktop are instances of these WPS
- classes. For example, there are probably a few folders, instances of the class
- WPFolder. Other objects are instances of WPPrinter, WPShredder, WPProgram,
- WPDataFile, etc. The WP Class List from the IBM Toolkit is itself an object
- listing the class hierarchy of all WPS classes (recall from the previous
- sections that all SOM classes (and therefore all WPS classes) form a hierarchy,
- showing the relationship between them). We'll use this tool later on.
-
- Another source of information regarding WPS classes and their use is the IBM
- Redbook volume 3: PM and Workplace Shell and Redbook volume 4: Application
- development. The latter provides very useful information about some methods
- and when they're called, along with more in-depth information about SOM and
- WPS. They are a good addition to this series and I recommend you read them
- thoroughly.
-
- WPS programming is in fact the creation of new classes, most of the time
- derived from existing WPS classes like WPDataFile, WPFolder, WPSound, and
- adding or overriding methods, to obtain a class that fits our needs. For
- example, you can create a password-protected folder class by deriving from
- WPFolder and overriding some methods. Because your new folder class inherits
- all methods from WPFolder, you don't have to write the code that implements the
- folder (opens a PM window, displays icons, supports drag and drop, etc.). The
- only thing you would do is plug your password protection code in by overriding
- a few methods. The trick here is getting to know for each WPS class what
- methods there are and what they do, so that you know what methods to override
- and why.
-
- This series will introduce some methods step by step, and show their function
- within WPS. Some methods are almost always overridden (the classics), while
- others are only used in specific cases. This introduction should encourage you
- to browse through the references to see what's possible.
-
- Tips
-
- From time to time you will encounter tips. Their purpose is mainly to keep
- beginning WPS programmers "on the right track". WPS programming has its fair
- share of problems and pitfalls, just like any form of programming. There are
- things you had better know about, or else you lose hours finding out what the
- problem is. There is nothing more frustrating than discovering that the "bug"
- you've been searching for all day really is a pecularity of the environment
- you're working in. So do read the tips if you want to save yourself hours of
- useless debugging. A tip looks like this:
-
- Tip
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.6. Making your first WPS object ΓòÉΓòÉΓòÉ
-
- Making your first WPS object
-
- OK, lets get started with this WPS programming business. I encourage you to
- actually compile the examples you'll find in this article, in order to really
- get the "look and feel" of WPS programming.
-
- To make your life easier, I've included a little program (WPS.CMD) that will
- ready the sample files for you. Thoughout this and the next article, I will
- mark some points as Step 1, Step 2, etc. When you see this, you can execute
- the WPS program with the number of the step as a parameter. This will give you
- all the needed files as they are in the article at the corresponding step,
- making it easy to compile and examine the examples and see the results of each
- step on your desktop. Please note this will only install the files that are
- different from the previous step, so don't skip any steps.
-
- Tip
-
- First Steps
-
- Suppose you have made a nifty program working with data files. Wouldn't it be
- very interesting if you could add "WPS integration" to the list of features?
- Why not make a WPS object class to represent your data files? That's exactly
- what we're going to do in this and the next article.
-
- So where do we start? You'll remember from the explanation of SOM programming
- that in order to create a new class, you need to make a .CSC file. Since we
- want to make a new data file, we derive from WPDataFile (this is the class
- behind the "Plain Text" Data File objects). The layout of our .CSC file is
- show in listing 1 below, also illustrating the syntax of the Object Interface
- Definition Language used in the class definition file.
-
- #******************************************************************************
- # Include the class definition file for the parent class
- #******************************************************************************
-
- include <wpdataf.sc>
-
- #******************************************************************************
- # Define the new class
- #******************************************************************************
-
- class: MyDataFile,
- external stem = dfd,
- local,
- external prefix = dfd_,
- classprefix = dfdM_,
- major version = 1,
- minor version = 1;
-
- --
- -- CLASS: MyDataFile
- --
- -- CLASS HIERARCHY:
- --
- -- SOMObject
- -- ΓööΓöÇΓöÇ WPObject
- -- ΓööΓöÇΓöÇ WPFileSystem
- -- ΓööΓöÇΓöÇ WPDataFile
- -- ΓööΓöÇΓöÇ MyDataFile
- --
-
- #******************************************************************************
- # Specify the parent class
- #******************************************************************************
-
- parent: WPDataFile;
-
- release order:
- wpclsQueryTitle,
- wpclsQueryInstanceType;
-
- passthru: C.ih;
-
- #define INCL_WIN
- #define INCL_DOS
- #include <os2.h>
-
- endpassthru;
-
-
- #******************************************************************************
- # Specify methods being overridden
- #******************************************************************************
-
- methods:
-
- #******************************************************************************
- # Specify class methods being overridden
- #******************************************************************************
-
- override wpclsQueryTitle, class;
- --
- -- METHOD: wpclsQueryTitle ( ) PRIVATE
- -- (X) PUBLIC
- -- DESCRIPTION:
- --
- -- Return the string "Datafile Deluxe".
- --
-
- override wpclsQueryInstanceType, class;
- --
- -- METHOD: wpclsQueryInstanceType ( ) PRIVATE
- -- (X) PUBLIC
- -- DESCRIPTION:
- --
- -- The wpclsQueryInstanceType method is called to allow the class
- -- object to specify the file type for instances of its
- -- class.
- --
- -- RETURNS:
- --
- -- A pointer to a string containing file type.
- --
-
- Listing 1
-
- The comments in a .CSC file can be either preceeded by a # or by --. When you
- use the latter, the comment is automatically included in the .C file that will
- be generated by the SOM compiler. If you look at the example, you can see it's
- in fact quite simple (most of it consists of comments). The sections in this
- file are as follows:
-
- include
- You should include the definitions for the parent class here (.SC
- file). In our example, we need the definitions of the WPDataFile
- class, which are in the file wpdataf.sc.
-
- class
- Information about the new class comes here. The most important item
- is the class name. The external stem is sometimes used by SOM to
- generate filenames, but is not very important. The prefixes will be
- used to create unique names for all methods, e.g. wpclsQueryTitle
- becomes dfdM_wpclsQueryTitle with the prefix in our .CSC file. As a
- shortcut, you can use _wpclsQueryTitle in the code to make it more
- readable. The version numbers will help determine if your DLL file
- is recent enough to provide the intended services.
-
- Tip
-
- parent
- Here you specify from what class you want to derive your new class,
- WPDataFile in our example.
-
- release order
- This tells the compiler in what order it should generate the generic
- function code.
-
- passthru
- Your implementation will sometimes need specific header files to be
- included or things like that. The place to put these is in the
- passthru: C.ih section. ih stands for implementation header, which
- is always included in the generated .C file.
-
- Tip
-
- methods
- Here you indicate all new methods you want to add, as well as the
- methods you want to override. Class methods are indicated by the
- word "class" at the end. For each method you specify here, the SOM
- compiler will generate a code stub for you to alter.
-
- These are the sections you should become familiar with, since they're almost
- always needed in order to define a new class (other sections are possible, but
- we won't use them here). It's a simple syntax, so you'll get used to it quite
- rapidly.
-
- You probably have noticed that our class definition file specifies two methods
- to be overridden. Both are class methods, and thus act upon the entire class.
- Let's look at what these methods do, and how we can add our own functionality.
-
- Step 1
-
- We will now compile our class definition file. I've included a makefile you
- can use for all your WPS programming (adapted from the makefile in the IBM
- toolkit). Remember: install the samples and then type WPS 1 in your working
- directory. This will give you the makefile and the class definition file from
- listing 1.
-
- Tip
-
- Compile the class definition file by typing the following in the working
- directory:
-
- NMAKE DATADEL.IH
-
- This will start the SOM compiler and generate a lot of files. One of these
- files is DATADEL.C (this is by far the most interesting one). The generated
- code stubs in this file look like listing 2:
-
- SOM_Scope PSZ SOMLINK dfdM_wpclsQueryTitle(M_MyDataFile *somSelf)
- {
- /* M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf); */
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryTitle");
-
- return (parent_wpclsQueryTitle(somSelf));
- }
-
- Listing 2
-
- This may at first seem a little crowded, but you'll learn to filter the unusual
- stuff out of it. First of all, read the first line as
-
- PSZ dfdM_wpclsQueryTitle(M_MyDataFile *somSelf)
-
- Now we have a function returning a PSZ (string) and accepting a pointer. The
- name of the function is wpclsQueryTitle, and in order to have unique names for
- your class, there's a dfdM prefixed to it. This is the prefix you specified as
- classprefix in the class definition file, since we're dealing with a class
- method. In the PM reference, you'll find all methods of each WPS class, and
- whether it is a normal method or a class method. For clarity, all class method
- contain cls as part of their name. So now you can see wpclsQueryTitle indeed
- is a class method. I'll explain what this method actually does later on.
-
- The second line of the stub is commented out. This code makes sure you can
- access the class data of your object, but since you don't have any class data,
- the SOM compiler has commented it out (in fact, you will get an error
- otherwise). Class data is data that applies to the class, so to all objects of
- that class. It can only be accessed by class methods.
-
- The third line uses the SOM system to identify this method for debugging
- purposes. Simply let this line be and it will be very happy.
-
- So the only remaining thing is the actual code of this method. It is really
- very simple:
-
- return (parent_wpclsQueryTitle(somSelf));
-
- You may already have guessed it: this code calls the wpclsQueryTitle of the
- parent class. This means that this code returns the exact same title as the
- WPDataFile class. Prefixing parent_ in SOM always results in calling the
- corresponding method of the parent class. This should almost always be done,
- since it allows the parent class to do its job too (most of the time, you only
- want to change part of the functionality, and you can let the parent do the
- rest of the work).
-
- The only thing remaining to be explained, is the somSelf pointer. This is a
- pointer SOM uses to know what object you're talking about. Remember: all
- instances of a class actually share the code of the methods. The only
- difference between the instances is the data. So in order to tell what
- particular instance a method should act upon, we pass it the somSelf pointer.
- In languages like C++, this is done automatically, here we must do it
- ourselves.
-
- With the gained knowledge, you can see that overriding the method and using the
- code generated by the SOM compiler as it is, has the same effect as not
- overriding the method at all. After all, if you don't override it, the
- parent's method gets called directly. But overriding a method provides you
- with a means to plug in your own code. I hope you can now see what WPS
- programming is all about: taking an existing class, such as WPDataFile, and
- selectively alter its behaviour. This way, you end up with your own class,
- behaving in a way exactly like the parent (by means of the inherited methods),
- and differently in another way (by means of overriding some methods).
-
- Now let's start changing some code. I haven't explained yet exactly what this
- wpclsQueryTitle method does. Well, it is used in WPS to query the title (read:
- name) of our class. The Workplace Shell calls this method every time it wants
- to know our title. This title will appear in the Templates folder, and will be
- the default name for all instances of the class. The first thing you should do
- when you create a new class in WPS is give that class its own title.
- Otherwise, you end up with different templates all having the same name, making
- it sometimes impossible to tell the difference between them. Moreover, your
- class will be identified by its title everywhere in the WPS, not only in the
- Templates folder, as we will see. For this reason, you'll need to always
- override the wpclsQueryTitle method.
-
- Step 2
-
- We will call our new class "Datafile Deluxe". We do this by changing the
- return statement generated by the SOM compiler to:
-
- return ("Datafile Deluxe");
-
- At this point, we have something we can compile to a DLL: by simply typing
-
- NMAKE
-
- This will build a DLL with the code for our new class (ignore the RC file for
- now). Now that we have the DLL, the next step is to register it. We do this
- by copying the DLL to a directory in our LIBPATH, and running the program
- REG.CMD (you should find it in your working directory):
-
- reg MyDataFile datadel
-
- The first parameter is the name of the class we want to register, the second
- parameter is the name of our DLL (without extension).
-
- Tip
-
- After a while, the class is registered. When you open the Templates folder,
- you can see the Datafile Deluxe template. Drag it to create an instance of our
- new class. Notice that our title also appears in the "Create another" submenu.
- Apart from the title, our object has exactly the same characteristics as
- objects of the WPDataFile class. For example, it still has the type "Plain
- Text" (see the settings notebook, under the tab "Type").
-
- See how easy it is to make your own WPS objects? Not counting the class
- definition file, we have written exactly one line of code, and we have an
- object that has a context menu, can be dragged, deleted, opened, edited,
- copied, has a settings notebook, and so on. Compare this to normal PM
- programming!
-
- So far, our new class hasn't been of much use. After all, it's nothing more
- than a simple data file, even if its title says otherwise. We do have a new
- class, however, and this already has some advantages. For example, you can
- tell any WPS folder only to include objects of this class: open its settings
- notebook and select the Include tab. Here you can see part of the WPS class
- hierarchy, not with the actual class names like WPDataFile, MyDataFile and so
- on, but with the class titles (this is another place where the class titles
- appear). You can easily see here that our class is derived from WPDataFile:
- it appears indented under the Data File item. To only include objects of our
- class, deselect Object, and select Datafile Deluxe (click somewhere else, e.g.
- in the Name field, to activate your last selection). Now we have a folder that
- only displays objects of our class.
-
- Perhaps more useful is the ability to find all objects of our class, wherever
- they are. To test this, drag a few templates to a variety of folders, then
- select Find from the desktop context menu. Here again we have part of the
- class hierarchy (see why the class title is so important?). Again deselect
- Object and select Datafile Deluxe. Don't forget to search all subfolders. The
- system will now find all Datafile Deluxe objects for you, on the desktop and in
- all subfolders.
-
- When you don't need the class anymore, you can deregister it. You do this by
- deleting all instances of the class and typing:
-
- dereg MyDataFile
-
- Tip
-
- You can use the WP Class List from the IBM toolkit to show the class hierarchy
- with the actual class names (see figure 1). This is also a handy tool to
- register and deregister classes, and to create instances of a class. Figure 1
- shows our class MyDataFile, derived from WPDataFile, which is in turn derived
- from WPFileSystem, and so on.
-
- Figure 1
-
- Step 3
-
- Let's make our class more useful by giving it its own type. We do this by
- overriding the wpclsQueryInstanceType method, just like we did with
- wpclsQueryTitle. We will return our title as the file type:
-
- return (_wpclsQueryTitle(somSelf));
-
- Using NMAKE again produces our DLL. After registering it (remember to copy it
- to your LIBPATH), make an instance of our class (drag the template). When you
- open the settings notebook, you can see it indeed has the type "Datafile
- Deluxe". We have used the same string for the class title and the instance
- type. This is to be preferred in general, since doing otherwise will only
- confuse the user. There's an exception to this: for some types, for example
- Icon, it is convenient to add the corresponding extension, for example .ICO, to
- the title. This convention is used in the standard WPS classes.
-
- So what's the impact of our introducing a new type on the WPS? Well, we now
- have an easy and unambiguous way of associating our data file with programs.
- To see this, make a new Program object (you know: drag the Program template),
- and provide a program name (for example, EPM.EXE). Then select the Association
- tab. Under Available types, look who's there! You can select Datafile Deluxe
- and put it under Current types, associating objects of our class with the
- program.
-
- Having objects of a distinct type can be advantageous when you have programs
- that generate their own datafiles. You can associate your datafiles with your
- program automatically if you use objects having a type of their own as
- datafiles (just like all objects of class MyDataFile), and add the ASSOCTABLE
- resource to your program. The first string in this resource is the type you
- want to associate your program with, Datafile Deluxe in our case (see the PM
- Reference for more info).
-
- If your program supports drag and drop, using a distinct type makes it very
- easy to recognize your own datafiles: the DRAGITEM structure for the item
- dropped on your program contains the hstrType string. This actually contains
- the type name of the object dropped on it. If you would drop an object of our
- MyDataFile class, this string would be "Datafile Deluxe". So the only thing
- you have to do if you want to accept your own datafiles, is using
- DrgVerifyTrueType with the name of the type you want to accept.
-
- In summary, using a distinct type makes it easy to recognize your own datafiles
- when they are dropped on your program, and allows users to simply double click
- a datafile, automatically opening your program. This is all unambiguous,
- unlike working with extensions: it's not because a file has the extension .DOT
- that it is one of your datafiles! But if it has type Datafile Deluxe, you're
- pretty sure it indeed is one of your files.
-
- Another View of Our Object.
-
- Up till now, we have only looked at the object side of our datafile. However,
- all objects of class WPDataFile, or derived from that class, actually represent
- real files, whereas objects of class WPFolder or a derived class represent real
- directories. In general, objects of class WPFileSystem represent "things" in a
- file system, that is: files or directories in the FAT or HPFS filesystems (it
- would be nice if the filesystem could also contain other objects, so that we
- could see our program objects in a directory listing, for example).
-
- Since our class MyDataFile is derived from WPDataFile, it actually represents a
- file. When you create an instance of the class, you actually create a new file
- (with zero size for now; later we'll see how to add data). So how does the WPS
- know this file is actually an object of class MyDataFile? The link between the
- file and the WPS object representing the file, is in the extended attributes of
- the file. There is an attribute called .CLASSINFO, where the class of the
- object is stored (among other things). This way, the WPS knows what methods it
- has to call in what DLL when the user manipulates the file.
-
- When we give our object a new type by overriding the wpclsQueryInstanceType
- method, this information is also stored in an extended attribute (.TYPE).
-
- If the files are copied or moved, OS/2 preserves the extended attributes, so
- the file keeps its object characteristics. The only problem is when you copy
- the file in plain DOS (not a DOS box). DOS knows absolutely nothing about
- EA's, and will only copy or move the contents of the file, not the other
- features. This results in lost extended attributes, in addition to demoting
- the object to a simple file.
-
- Summarizing: all information about the object is stored in EA's. To put it
- another way (more intimidating): objects of class WPFileSystem or a derived
- class are stored on disk and achieve persistence through extended attributes
- (impress your friends with this one).
-
- Knowing that, since our class is derived from WPDataFile, objects of the class
- indeed are datafiles, you know everything you need to make programs using our
- new objects. As far as your program is concerned, it is working with files
- (having a few special extended attributes). Your program can open, read,
- write, close the file, just like any other file. The fact that those files are
- WPS objects (because of the EA's) accounts for the WPS integration of your
- datafiles. When your program creates a new file, it has to make sure the file
- contains the correct EA's. The easiest way to do this is by using
- WinCreateObject. This function creates an instance of the class you specify.
- This automatically creates the file and the correct EA's.
-
- Step 4
-
- You've probably wondered what the RC file is doing. Well, until now, nothing
- at all! We'll use it now to demonstrate how to load resources from the class
- DLL. We need the module handle of the DLL for this, so we will first create a
- new method called clsQueryModuleHandle. This method will return the handle of
- our DLL. We store the handle in the variable hmod, so the next time anyone
- calls this method, we can simply return this variable.
-
- This is the right time to discuss class data. Remember an object contains
- methods and data. This data is called instance data, since it is unique for
- each instance. In SOM, you can also define class data, for things that all
- instances of the class have in common. The module handle of the DLL would seem
- to be an ideal candidate for storing in class data: it is a value all
- instances of the class share. Well, conceptually this is true, but alas there
- is a little problem. Class data can only be accessed by class methods, not by
- normal (instance) methods. Since we will want to access the module handle from
- normal methods later on, we don't store it in class data. Instead, we use a
- file scope variable in the file DATADEL.C (hmod).
-
- The class title, however, can be stored in class data. There are two things we
- should do to make this work: we need to declare the class data in our class
- definition file, and we must override the wpclsInitData method. This method is
- called to initialize class data, so it is the perfect method for reading our
- title from the resources and storing in in class data.
-
- The complete class definition file at this point is as in listing 3 (the new
- items are in red). It should be fairly obvious what's going on.
-
- #******************************************************************************
- # Include the class definition file for the parent class
- #******************************************************************************
-
- include <wpdataf.sc>
-
- #******************************************************************************
- # Define the new class
- #******************************************************************************
-
- class: MyDataFile,
- external stem = dfd,
- local,
- external prefix = dfd_,
- classprefix = dfdM_,
- major version = 1,
- minor version = 1;
-
- --
- -- CLASS: MyDataFile
- --
- -- CLASS HIERARCHY:
- --
- -- SOMObject
- -- ΓööΓöÇΓöÇ WPObject
- -- ΓööΓöÇΓöÇ WPFileSystem
- -- ΓööΓöÇΓöÇ WPDataFile
- -- ΓööΓöÇΓöÇ MyDataFile
- --
-
- #******************************************************************************
- # Specify the parent class
- #******************************************************************************
-
- parent: WPDataFile;
-
- release order:
- clsQueryModuleHandle,
- wpclsQueryTitle,
- wpclsQueryInstanceType,
- wpclsInitData;
-
- passthru: C.ih;
-
- #define INCL_WIN
- #define INCL_DOS
- #include <os2.h>
- #include "datares.h"
- #include <string.h>
- endpassthru;
-
- data:
-
- UCHAR szTitle[CCHMAXPATH], class;
-
- #******************************************************************************
- # Specify methods being overridden
- #******************************************************************************
-
- methods:
-
- #******************************************************************************
- # Specify class methods being overridden
- #******************************************************************************
-
- override wpclsInitData, class;
- --
- -- METHOD: wpclsInitData
- --
- -- DESCRIPTION:
- --
- -- Initalize the class data
- --
-
- override wpclsQueryTitle, class;
- --
- -- METHOD: wpclsQueryTitle ( ) PRIVATE
- -- (X) PUBLIC
- -- DESCRIPTION:
- --
- -- Returns the title of our class.
- --
-
- override wpclsQueryInstanceType, class;
- --
- -- METHOD: wpclsQueryInstanceType ( ) PRIVATE
- -- (X) PUBLIC
- -- DESCRIPTION:
- --
- -- The wpclsQueryInstanceType method is called to allow the class
- -- object to specify the file type for instances of its
- -- class.
- --
- -- RETURNS:
- --
- -- A pointer to a string containing file type.
- --
-
-
- #******************************************************************************
- # Define class methods
- #******************************************************************************
-
- HMODULE clsQueryModuleHandle (), class;
- --
- -- METHOD: clsQueryModuleHandle ( ) PRIVATE
- -- (X) PUBLIC
- -- DESCRIPTION
- --
- -- This method returns the module handle of this class. If this is the
- -- first invocation, DosQueryModuleHandle is called to save the handle
- -- for future invocations.
- --
- -- RETURN:
- --
- -- 0 Unsuccessful
- -- non-zero module handle
- --
- Listing 3
-
- When you use the SOM compiler (type NMAKE DATADEL.IH), it will append the new
- methods to DATADEL.C (you have to move the methods manually if you don't want
- them at the end of your source file). Looking at the generated code for
- clsQueryModuleHandle, we can see that adding a method is not different from
- overriding one, except we can't call the parent, since it doesn't have our
- method. Notice that the first line in each added method is now uncommented,
- since we have class data. This line is still commented out in the older
- methods, since they were generated when there was no class data, and the SOM
- compiler doesn't change any code already in the source file.
-
- Step 5
-
- Listing 4 shows the code for our clsQueryModuleHandle method. The only really
- new item here is the call to _somLocateClassFile. This is a method of
- SOMClassMgrObject, returning the pathname of the DLL that contains the code for
- the class whose ID is specified as the second parameter (whew). We obtain this
- ID with a call to SOM_IdFromString, giving it the name of our class. After we
- obtain the full pathname of our DLL, we simply query its handle.
-
- SOM_Scope HMODULE SOMLINK dfdM_clsQueryModuleHandle(M_MyDataFile *somSelf)
- {
- APIRET rc;
-
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_clsQueryModuleHandle");
-
- if (hmod == NULLHANDLE) {
- zString zsPathName;
- zsPathName = _somLocateClassFile(SOMClassMgrObject,
- SOM_IdFromString("MyDataFile"),
- MyDataFile_MajorVersion, MyDataFile_MinorVersion);
- rc = DosQueryModuleHandle(zsPathName, &hmod);
- if (rc) {
- WinMessageBox(HWND_DESKTOP, HWND_DESKTOP,
- (PSZ) "MyDataFile::dfdM_clsQueryModuleHandle",
- (PSZ) "Cannot load module handle",
- 20,
- MB_OK | MB_INFORMATION | MB_MOVEABLE);
- return (HMODULE) 0;
- }
- }
- return hmod;
- }
-
- Listing 4
-
- Now that we have a way of obtaining the module handle of our DLL, implementing
- the loading of our title is really simple (see listing 5).
-
- SOM_Scope void SOMLINK dfdM_wpclsInitData(M_MyDataFile *somSelf)
- {
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsInitData");
-
- if (!WinLoadString(WinQueryAnchorBlock(HWND_DESKTOP),
- _clsQueryModuleHandle(somSelf),
- ID_TITLE, sizeof(_szTitle), _szTitle))
- strcpy(_szTitle, parent_wpclsQueryTitle(somSelf));
-
- parent_wpclsInitData(somSelf);
- }
-
- Listing 5
-
- Notice in listing 5 how we access our class data: The first line of the code
- should not be commented out, and we use an underscore to access the title. In
- fact, _szTitle really is a shortcut, and it is defined as #define _szTitle
- (somThis->szTitle) in datadel.ih (the SOM compiler has done this for us). This
- explains why the first line is needed and may help you interpret compiler
- errors when you later forget to uncomment that line in other methods.
- Prefixing an underscore is not only used to access the data, but also to access
- the methods, as you can see in the call to clsQueryModuleHandle.
-
- Listing 5 also illustrates how you obtain an anchor block for your WPS code:
- simply obtain the one from the desktop. This makes sense, since all WPS code
- actually runs in the PMSHELL.EXE process.
-
- The only remaining thing to do is modifying the wpclsQueryTitle method, since
- it should return the title we loaded into szTitle:
-
- SOM_Scope PSZ SOMLINK dfdM_wpclsQueryTitle(M_MyDataFile *somSelf)
- {
- M_MyDataFileData *somThis = M_MyDataFileGetData(somSelf);
- M_MyDataFileMethodDebug("M_MyDataFile","dfdM_wpclsQueryTitle");
-
- return (_szTitle);
- }
-
- Remember to uncomment the first line! The SOM compiler doesn't change the code
- we already have, so we have to do it manually. Later, we will use other
- resources from the DLL, so our clsQueryModuleHandle method will again be put to
- good use.
-
- Tip
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 2.7. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- In this article, I've introduced WPS programming by first explaining concepts
- from object oriented programming and SOM programming. This allows you to
- understand what's going on. After that, we have made our first WPS class,
- edited it, compiled it, registered it and used it. This first introduction
- should give you a fairly good idea of what a WPS class really is, and what WPS
- programming is all about.
-
- The class we've made so far is not very special. In fact, some of its features
- can be achieved with normal OS/2 programming (for example, the .TYPE EA). But
- it already shows some WPS integration, for example the ability to locate all
- objects of the class. This minimal form of integration may be all that is
- needed, and it may be easier to create a WPS object than to manually write the
- .TYPE EA to your datafiles.
-
- Next time, we will improve the WPS integration, by discussing more methods and
- showing what the effect is of overriding them.
-
- If you have any comments, corrections, additions, or whatever, feel free to
- contact me (see elsewhere in this issue for information on how to reach me).
-
- WPS Programming the Easy Way (Part 1) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 3. The Design and Implementation of VIOWIN - Part 1 ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 3.1. Introduction ΓòÉΓòÉΓòÉ
-
- VIOWIN (The Fullscreen PM Subset) - Part 1
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- For my job, I once had to write an application that ran only when OS/2 booted
- from the floppy diskettes. Because I had no access to the functionality PM
- provides, I resorted to a line-oriented interface, where messages were
- displayed on the screen and scrolled up when necessary. It was a good
- interface, I thought; it was fully NLS enabled and had intelligent defaults so
- the user basically only had to type in the name of the application.
- Unfortunately, the Quality Assurance team didn't concur with my opinion. "We
- want a nice interface!" one exclaimed. "Yeah, one with different windows and
- such!" another shouted.
-
- I was backed into a corner that I could only get out of one way.
-
- This series will describe the design and implementation of VIOWIN, a library
- that implements a subset of the Win APIs provided by PM for fullscreen
- sessions. The reasoning behind writing this series is that it provided me and
- will hopefully provide you with some unique insights into how a windowing
- system is developed; and since it is based on PM, your familiarity with the
- already defined interface will increase your capability to fully understand
- what is being described.
-
- Obviously, this series assumes you have PM application development experience,
- but it isn't required.
-
- The Design and Implementation of VIOWIN (Part 1) - EDM/2 - Sept 1994 - Volume
- 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 3.2. Forethought ΓòÉΓòÉΓòÉ
-
- Forethought
-
- Before I could begin coding, I had to decide where to draw the line. I
- couldn't reasonably expect to implement the entire API set, but I didn't want
- to limit the capabilities of the library unnecessarily. I must apologize
- because I did not take any notes when developing this, so the "list" of
- limitations is probably incomplete. Most of the limitations were chosen to
- save time coding the library; after all, I did have an application to write
- using this library and only two weeks total to complete all of it!
-
- The design points are listed below. First are the "have not's":
-
- 1. No multiprocess or multithread application support.
- 2. No overlapping window support.
- 3. No movable window support.
- 4. No mouse support.
- 5. No profile support.
- 6. No class styles.
-
- ...followed by the "have's":
-
- 1. At least 3 implemented window classes - buttons, entryfields, and statics.
- 2. Input focus support.
- 3. Timer support.
- 4. Cursor support.
- 5. Limited resource support.
- 6. Window styles.
-
- For the window classes, not all styles were implemented (e.g. text fields and
- group boxes were written, but not rectangles or bitmaps), nor were all messages
- in each class implemented.
-
- Cursor support is limited, due to the nature of the system. Since we are
- running in a character-mode fullscreen session, we cannot have dotted boxes
- around the text of a button, for example.
-
- The only resource support that made it into the current version is for the
- STRINGTABLE. I would have liked to have added ACCELTABLE and DIALOGTEMPLATE
- support, but didn't have the time to do it.
-
- Additionally, I wanted to have as much similarity to the Win APIs as I could
- possibly design and code. Thus, there is an anchor block and message queue
- (although they are hidden), message loops, window procedures, etc. The
- advantages here are that 1) I didn't have to spend additional time designing
- the paradigm on which my design would be based and 2) users of the library
- would already be familiar with the ideas, providing they had PM application
- development experience.
-
- There are also some things not mentioned above that were included. I avoided
- the issue of output completely by choosing to leave out the Gpi APIs (for
- obvious reasons), but the static control, for example, had to be able to write
- its text out. Thus, the vwDrawText() function was added. Also, for the
- limited clipping provided in functions such as vwDrawText(), rectangle support
- was added. Also, certain system values were added, as well as the
- vwQuerySysValue() and vwSetSysValue() functions, and vwAlarm() was needed for
- audible feedback.
-
- The base library consists of the files listed below, followed by a list of the
- files comprising the window classes, which were kept separate to encourage good
- programming.
-
- VIOWIN.C Main module, containing miscellaneous functions.
- VWCLASS.C Window class support.
- VWCURS.C Cursor support.
- VWDRAW.C Drawing support.
- VWMSG.C Message support.
- VWRECT.C Rectangle support.
- VWRES.C Resource support.
- VWTIMER.C Timer support.
- VWUTIL.C Utility functions needed by the library.
- VWWND.C Window functions.
-
- CLASSES.C Main module, which registers the window classes.
- CLBT.C Button class.
- CLEF.C Entryfield class.
- CLLB.C Listbox class, never implemented.
- CLSB.C Scrollbar class, never implemented.
- CLST.C Static class.
-
- It should be noted here that exploitation of the Common/2 library was used
- whenever possible (especially for the linked-list routines). If you are not
- familiar with this library, it is recommended that you get the latest version
- (currently 1.6.0) from ftp.cdrom.com.
-
- Throughout this series, I will describe each module in depth along with any
- notes that pop into my head. I realize that this will detract from the
- readability of the articles, but - again - I did not originally intend for this
- series to even exist or for the library to grow to what it has become.
-
- The Design and Implementation of VIOWIN (Part 1) - EDM/2 - Sept 1994 - Volume
- 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 3.3. Data Structures ΓòÉΓòÉΓòÉ
-
- Data Structures
-
- This month, we will only look at the four predominant data structures involved.
- Additional data structures will be discussed as the code involving them is
- described. Next month, we will delve into the code proper, and the code will
- be provided with the next article so that you can do your own "armchair
- detecting." (This also gives me more time to insure that the code is
- well-commented, etc. <grin>)
-
- Note!
-
- You will notice that vw is the prevailing prefix used throughout the code.
- This applies to function names, data types, constants, etc. A side effect of
- this is that, since there is HVWWND instead of HWND (et al.), many structures
- had to be redefined to specify the new data type instead of the original
- version. This is tedious at best, and is avoided whenever possible.
-
- The Anchor Block Structure
-
- typedef struct _VWAB {
- ULONG ulSzStruct;
- ULONG ulStatus;
- HCMMEM hcmWork;
- HCLLIST hclClasses;
- HCLLIST hclWindows;
- HCLLIST hclTimers;
- HMODULE hmClasses;
- BOOL bIsSendMsg;
- struct _VWWND *hwndFocus;
- struct _VWCURSORINFO *pciCursor;
- USHORT usCursorState;
- LONG alSysValues[VWSV_CSYSVALUES];
- } VWAB, *HVWAB;
-
- The anchor block data structure, shown above, is used to maintain general
- housekeeping data on the state of the process as a whole (vs per thread in PM).
- The fields are described below:
-
- ulSzStruct (ULONG) - size of the structure, because I am afraid that
- there is still some thunking going on in the kernel.
- ulStatus (ULONG) - status of the library (VW_HABST_* constant).
- hcmWork (HCMMEM) - heap manager instance for general purpose
- consumption.
- hclClasses (HCLLIST) - linked-list of VWCLASSINFO structures defining
- each registered window class.
- hclWindows (HCLLIST) - linked-list of VWWND structures defining the
- existing windows.
- hclTimers (HCLLIST) - linked-list of VWTIMERINFO structures defining
- the timers in use.
- hmClasses (HMODULE) - handle of the DLL containing the predefined
- classes.
- bIsSendMsg (BOOL) - flag set when vwSendMsg() is called.
- hwndFocus (HVWWND) - handle of the window with the input focus.
- pciCursor (HVWCURSORINFO) - describes the cursor information. I
- cannot remember exactly why this is a pointer and not the
- structure itself.
- usCursorState (USHORT) - a VWCS_* constant, used internally.
- alSysValues (LONG) - an array of the system values.
-
- The Class Information Structure
-
- typedef struct _VWCLASSINFO {
- CHAR achName[256];
- PFNVWWP pfnWndProc;
- } VWCLASSINFO, *PVWCLASSINFO;
-
- achName is the name of the class as registered and pfnWndProc is a pointer to
- the associated window procedure.
-
- The Window Structure
-
- typedef struct _VWWND {
- ULONG ulSzStruct;
- struct _VWCLASSINFO *pciClass;
- USHORT usId;
- ULONG ulStyle;
- VWSWP swpSwp;
- LONG lForeClr;
- LONG lBackClr;
- PCHAR pchText;
- PVOID pvData[2];
- } VWWND, *HVWWND;
-
- ulSzStruct (ULONG) - again, because I am paranoid.
- pciClass (PVWCLASSINFO) - pointer to the VWCLASSINFO structure so to
- optimize the vwSendMsg() function.
- usId (USHORT) - identifier of the window. Like PM, an id of -1
- means that you don't care about the identifier and a
- "duplicate id" check is not made.
- ulStyle (ULONG) - window style.
- swpSwp (VWSWP) - size and position of the window.
- lForeClr (LONG) - foreground color. See below.
- lBackClr (LONG) - background color. See below.
- pchText (PCHAR) - window text.
- pvData (PVOID) - array (yes, I too just noticed the incorrect
- field name according to Hungarian notation) of window data.
- The window classes use index 1 and the application can use
- 0.
-
- Note!
-
- The colors are a necessary deviation from PM since there is no Gpi support.
- Instead of having each window class allocate and manage window words, I decided
- to do it instead, since it would be a frequently used piece of information.
-
- Message Queue Structure
-
- typedef struct _VWMQ {
- ULONG ulSzStruct;
- VWQMSG aqmMsgs[VW_SIZEQUEUE];
- ULONG ulHead;
- ULONG ulTail;
- } VWMQ, *HVWMQ;
-
- ulSzStruct (ULONG) - again, because I am paranoid.
- aqmMsgs (VWQMSG) - array of VWQMSG structures containing the
- contents of the queue.
- ulHead (ULONG) - index of the front of the queue.
- ulTail (ULONG) - index of the rear of the queue.
-
- Note!
-
- This is a circular queue.
-
- The Design and Implementation of VIOWIN (Part 1) - EDM/2 - Sept 1994 - Volume
- 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 3.4. Next Month ΓòÉΓòÉΓòÉ
-
- Next Month
-
- That's it for this month. I hope I have whet your appetite with this
- installment. Next month, we will begin looking at the primary modules in the
- library, which will be followed in subsequent month's by the other,
- not-as-important modules, and finally by the window classes.
-
- Any comments are most definately welcome to my email address. See you next
- month!
-
- The Design and Implementation of VIOWIN (Part 1) - EDM/2 - Sept 1994 - Volume
- 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4. Sprites and Animation - Reprise ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 4.1. Introduction ΓòÉΓòÉΓòÉ
-
- Sprites and Animation - Reprise
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- And when you had thought that this topic had been exhaustively treated, here it
- comes again. This final article of the series will discuss the necessary
- changes to implement z-ordering within the sprite library; these changes will
- be discussed using the Common/2 library. Have no fear, however; as promised,
- the source for the module has been included with this article.
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4.2. Voodoo Chili (Slight Return) ΓòÉΓòÉΓòÉ
-
- Voodoo Chili (Slight Return)
-
- (Yes, the misspelling was intended.)
-
- When you think of z-ordering, you think of layering. The problem of designing
- and implementing z-ordering was approached with the latter term in mind, since
- it helps ease the transition from the abstract to the codable. Consider the
- algorithm for drawing a sprite, given the concept of sprite layering:
-
- 1. Draw the background
-
- 2. Draw all sprites below the sprite to be drawn (the current sprite), if and
- only if they overlap the bounding rectangle of the current sprite.
-
- 3. Draw the current sprite.
-
- 4. Draw all sprites above the current sprite, if and only if they overlap the
- bounding rectangle of the current sprite.
-
- Simple enough, eh? Before you roll up your sleeves to code this yourself
- <grin>, consider the following:
-
- 1. How the sprites are to be drawn
- 2. Performance
-
- Drawing
-
- The first item can no longer use the method developed in the first part of this
- series (see EDM/2 - Volume 2, Issue 5), since that blatently overpaints the
- bounding rectangle of the current sprite with the corresponding section of the
- background, effectively wiping out the drawing of the underlying sprites noted
- in step 2 of the drawing algorithm. Instead, we must draw each sprite sans
- background, in order to preserve the sprites below the current sprite. To get
- the background, then, we draw it as a separate step.
-
- Of course, this requires modification to our drawing routines, as we will see
- shortly.
-
- Performance
-
- Then, there is the issue of performance. Given the worst-case scenario,
- suppose all sprites are of the maximum size, and they all overlap the current
- sprite. When we have to draw the current sprite, if we completely (that's the
- operative word) draw each of the overlapping sprites, our performance drops
- through the floor. Instead, we should calculate which portion of each
- overlapping sprite is actually overlapping and draw only that. This requires
- more thought up front, but saves us much in the long run.
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4.3. Coding the Changes ΓòÉΓòÉΓòÉ
-
- Coding the Changes
-
- Before any coding can take place, we must understand how z-ordering will be
- represented in the data structures. The easiest way, in my opinion, is by
- changing the interpretation of the current data structures, i.e. use the array
- of sprites in the playground data structure (ahsSprites). The handle in index
- 0 is the bottom-most sprite, while the handle in the highest index is the
- top-most sprite. This is nice, because it enables us to use simple for-loops
- when enumerating the sprites by z-order.
-
- There are three routines which have changed to implement z-ordering:
- drawSpriteAt(), CmnSprDrawSprite(), and CmnSprSetSpritePosition(). We look at
- each of these in detail below.
-
- drawSpriteAt()
-
- This workhorse function of the drawing routines now accepts the rectangle of
- the sprite to be drawn, assuming a lower-left corner of (0,0).
-
- static BOOL drawSpriteAt(HPS hpsDraw,
- HCSSPRITE hsSprite,
- PSIZEL pszlPlay,
- PPOINTL pptlSprite,
- PRECTL prclSprite)
- //-------------------------------------------------------------------------
- // This function draws the sprite at the specified position. It is assumed
- // that the background has already been drawn into hpsDraw before this
- // function is called.
- //
- // Input: hpsDraw - handle of the presentation space to draw in
- // hsSprite - handle of the sprite to draw
- // pszlPlay - points to the size of hpsDraw. If NULL, the size
- // of the playground is used.
- // pptlSprite - points to the point specifying the position. If
- // NULL, the sprite's current position is used.
- // prclSprite - points to the rectangle within the sprite to draw,
- // i.e. a rectangle bounded by (0,0)-(cx,cy) which
- // is added to the sprite's position to determine
- // how much of the sprite is to be drawn. If NULL,
- // the entire sprite is drawn.
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
-
- The change in the code is actually quite simple. Instead of assuming (0,0) as
- the lower left corner and (cx,cy) as the upper right corner, we use the values
- provided (if provided).
-
- {
- SIZEL szlUsePlay;
- POINTL ptlUseSpr;
- RECTL rclUseSpr;
- POINTL aptlPoints[4];
-
- if ((!hsSprite->hpgPlay->bUpdate) || (!hsSprite->bVisible)) {
- return TRUE;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Initialize the local variables with either what was passed in or
- // the defaults as noted above in the function prologue
- //----------------------------------------------------------------------
- if (pszlPlay==NULL) {
- CmnSprQueryPlaygroundSize(hsSprite->hpgPlay,&szlUsePlay);
- } else {
- szlUsePlay=*pszlPlay;
- } /* endif */
-
- if (pptlSprite==NULL) {
- ptlUseSpr=hsSprite->ptlPos;
- } else {
- ptlUseSpr=*pptlSprite;
- } /* endif */
-
- if (prclSprite==NULL) {
- rclUseSpr.xLeft=0;
- rclUseSpr.yBottom=0;
- rclUseSpr.xRight=hsSprite->bmihMask.cx;
- rclUseSpr.yTop=hsSprite->bmihMask.cy;
- } else {
- rclUseSpr=*prclSprite;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Convert the xRight/yTop pair to the size of the sprite
- //----------------------------------------------------------------------
- rclUseSpr.xRight-=rclUseSpr.xLeft;
- rclUseSpr.yTop-=rclUseSpr.yBottom;
-
- aptlPoints[0].x=ptlUseSpr.x+rclUseSpr.xLeft;
- aptlPoints[0].y=ptlUseSpr.y+rclUseSpr.yBottom;
- aptlPoints[1].x=aptlPoints[0].x+rclUseSpr.xRight-1;
- aptlPoints[1].y=aptlPoints[0].y+rclUseSpr.yTop-1;
- aptlPoints[2].x=rclUseSpr.xLeft;
- aptlPoints[2].y=rclUseSpr.yBottom;
- aptlPoints[3].x=aptlPoints[2].x+rclUseSpr.xRight;
- aptlPoints[3].y=aptlPoints[2].y+rclUseSpr.yTop;
-
- if (clipBltPoints(hsSprite->habAnchor,aptlPoints,&szlUsePlay)) {
- //-------------------------------------------------------------------
- // Blit the mask and then the bitmap
- //-------------------------------------------------------------------
- GpiWCBitBlt(hpsDraw,
- hsSprite->hbmMask,
- 4,
- aptlPoints,
- ROP_SRCAND,
- BBO_IGNORE);
-
- GpiWCBitBlt(hpsDraw,
- hsSprite->hbmBitmap,
- 4,
- aptlPoints,
- ROP_SRCPAINT,
- BBO_IGNORE);
- } /* endif */
-
- return TRUE;
- }
-
- CmnSprDrawSprite()
-
- This code no longer is so concise, although it still is rather simple. We do
- not simply call drawBackAt(), drawSpriteAt(), and return; now, we must loop
- through the sprites, drawing the intersecting rectangles of each. Note: the
- intersecting rectangle of the current sprite with itself is an identity
- function, so no special checking needs to be performed.
-
- SPRERROR EXPENTRY CmnSprDrawSprite(HPS hpsDraw,HCSSPRITE hsSprite)
- //-------------------------------------------------------------------------
- // This function draws a sprite
- //
- // Input: hpsDraw - handle to the HPS to draw the sprite in
- // hsSprite - handle to the sprite
- // Returns: SPR_ERR_NOERROR if successful, SPR_ERR_* constant otherwise
- //-------------------------------------------------------------------------
- {
- USHORT usSemAction;
- RECTL rclSprite;
- ULONG ulIndex;
- HCSSPRITE hsLayer;
- RECTL rclLayer;
- RECTL rclInter;
-
- if (queryHandle(hsSprite)!=QH_HCSSPRITE) {
- return SPR_ERR_BADHANDLE;
- } /* endif */
-
- usSemAction=accessSem((PCMNHANDLE)hsSprite,ACCSEM_SET);
-
- if (hsSprite->hpgPlay==NULL) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_HASNOPLAYGROUND;
- } /* endif */
-
- if ((!hsSprite->bVisible) || (!hsSprite->hpgPlay->bUpdate)) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOERROR;
- } /* endif */
-
- CmnSprQuerySpriteRect(hsSprite,&rclSprite);
-
- rclSprite.xRight++;
- rclSprite.yTop++;
-
- drawBackAt(hpsDraw,hsSprite->hpgPlay,NULL,NULL,&rclSprite);
-
- rclSprite.xRight--;
- rclSprite.yTop--;
-
- for (ulIndex=0; ulIndex<hsSprite->hpgPlay->ulNumMembers; ulIndex++) {
- hsLayer=hsSprite->hpgPlay->ahsSprites[ulIndex];
-
- CmnSprQuerySpriteRect(hsLayer,&rclLayer);
-
- WinIntersectRect(hsSprite->hpgPlay->habAnchor,
- &rclInter,
- &rclSprite,
- &rclLayer);
-
- if (!WinIsRectEmpty(hsSprite->hpgPlay->habAnchor,&rclInter)) {
- rclInter.xLeft-=rclLayer.xLeft;
- rclInter.yBottom-=rclLayer.yBottom;
- rclInter.xRight-=rclLayer.xLeft;
- rclInter.yTop-=rclLayer.yBottom;
-
- rclInter.xRight++;
- rclInter.yTop++;
-
- drawSpriteAt(hpsDraw,hsLayer,NULL,NULL,&rclInter);
- } /* endif */
- } /* endfor */
-
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOERROR;
- }
-
- It should be obvious that the real work is done in the loop body. If there is
- an intersection of bounding rectangles, a call to drawSpriteAt() is made.
-
- CmnSprSetSpritePosition()
-
- Of the three functions, this one has the most new code, but that isn't saying
- much, since the code up to this point hasn't been very difficult to understand.
- If you'll remember, this function takes one of two paths, depending on whether
- the new position overlaps the old. Fortunately for us, in the original code,
- one of the paths called CmnSprDrawSprite(), so no change is needed in that
- case.
-
- SPRERROR EXPENTRY CmnSprSetSpritePosition(HPS hpsDraw,
- HCSSPRITE hsSprite,
- PPOINTL pptlNew)
- //-------------------------------------------------------------------------
- // This function changes the position of the sprite. This function is
- // optimized so that, if the rectangle bounding the sprite at the new
- // position overlaps the old, only one "bit blit" to the specified HPS
- // is done, eliminating flicker.
- //
- // Input: hpsDraw - handle to the HPS to draw the sprite in once it is
- // moved
- // hsSprite - handle to the sprite
- // Returns: SPR_ERR_NOERROR if successful, SPR_ERR_* constant otherwise
- //-------------------------------------------------------------------------
- {
- USHORT usSemAction;
- SIZEL szlPlay;
- SIZEL szlWork;
- RECTL rclOld;
- RECTL rclNew;
- RECTL rclUnion;
- RECTL rclSrc;
- RECTL rclDest;
- ULONG ulIndex;
- HCSSPRITE hsLayer;
- RECTL rclLayer;
- RECTL rclInter;
- POINTL ptlWork;
- POINTL aptlPoints[4];
-
- if (queryHandle(hsSprite)!=QH_HCSSPRITE) {
- return SPR_ERR_BADHANDLE;
- } /* endif */
-
- usSemAction=accessSem((PCMNHANDLE)hsSprite,ACCSEM_SET);
-
- if (hsSprite->hpgPlay==NULL) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_HASNOPLAYGROUND;
- } /* endif */
-
- if ((hsSprite->bVisible) && (hsSprite->hpgPlay->bUpdate)) {
- szlWork.cx=MAX_SPRITE_CX*2;
- szlWork.cy=MAX_SPRITE_CY*2;
-
- CmnSprQueryPlaygroundSize(hsSprite->hpgPlay,&szlPlay);
-
- CmnSprQuerySpriteRect(hsSprite,&rclOld);
- hsSprite->ptlPos=*pptlNew;
- CmnSprQuerySpriteRect(hsSprite,&rclNew);
-
- WinUnionRect(hsSprite->habAnchor,&rclUnion,&rclOld,&rclNew);
-
- if ((rclUnion.xRight-rclUnion.xLeft>MAX_SPRITE_CX*2) ||
- (rclUnion.yTop-rclUnion.yBottom>MAX_SPRITE_CY*2)) {
-
- rclSrc.xLeft=rclOld.xLeft;
- rclSrc.yBottom=rclOld.yBottom;
- rclSrc.xRight=rclSrc.xLeft+hsSprite->bmihBitmap.cx;
- rclSrc.yTop=rclSrc.yBottom+hsSprite->bmihBitmap.cy;
-
- drawBackAt(hpsDraw,hsSprite->hpgPlay,NULL,NULL,&rclSrc);
-
- CmnSprDrawSprite(hpsDraw,hsSprite);
- } else {
- rclSrc=rclUnion;
- rclSrc.xRight++;
- rclSrc.yTop++;
-
- rclDest.xLeft=0;
- rclDest.yBottom=0;
- rclDest.xRight=rclUnion.xRight-rclUnion.xLeft;
- rclDest.yTop=rclUnion.yTop-rclUnion.yBottom;
-
- drawBackAt(hsSprite->hpgPlay->hpsWork,
- hsSprite->hpgPlay,
- &rclDest,
- &szlWork,
- &rclSrc);
-
- for (ulIndex=0; ulIndex<hsSprite->hpgPlay->ulNumMembers; ulIndex++) {
- hsLayer=hsSprite->hpgPlay->ahsSprites[ulIndex];
-
- CmnSprQuerySpriteRect(hsLayer,&rclLayer);
-
- WinIntersectRect(hsSprite->hpgPlay->habAnchor,
- &rclInter,
- &rclUnion,
- &rclLayer);
-
- if (!WinIsRectEmpty(hsSprite->hpgPlay->habAnchor,&rclInter)) {
- ptlWork.x=hsLayer->ptlPos.x-rclUnion.xLeft;
- ptlWork.y=hsLayer->ptlPos.y-rclUnion.yBottom;
-
- rclInter.xLeft-=rclLayer.xLeft;
- rclInter.yBottom-=rclLayer.yBottom;
- rclInter.xRight-=rclLayer.xLeft;
- rclInter.yTop-=rclLayer.yBottom;
-
- rclInter.xRight++;
- rclInter.yTop++;
-
- drawSpriteAt(hsSprite->hpgPlay->hpsWork,
- hsLayer,
- &szlWork,
- &ptlWork,
- &rclInter);
- } /* endif */
- } /* endfor */
-
- //----------------------------------------------------------------
- // GpiBitBlt is non-inclusive on source AND target
- //----------------------------------------------------------------
- aptlPoints[0].x=rclUnion.xLeft;
- aptlPoints[0].y=rclUnion.yBottom;
- aptlPoints[1].x=rclUnion.xRight+1;
- aptlPoints[1].y=rclUnion.yTop+1;
- aptlPoints[2].x=0;
- aptlPoints[2].y=0;
- aptlPoints[3].x=rclUnion.xRight-rclUnion.xLeft+1;
- aptlPoints[3].y=rclUnion.yTop-rclUnion.yBottom+1;
-
- if (clipBltPoints(hsSprite->habAnchor,aptlPoints,&szlPlay)) {
- GpiBitBlt(hpsDraw,
- hsSprite->hpgPlay->hpsWork,
- 4,
- aptlPoints,
- ROP_SRCCOPY,
- BBO_IGNORE);
- } /* endif */
- } /* endif */
- } else {
- hsSprite->ptlPos=*pptlNew;
- } /* endif */
-
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOERROR;
- }
-
- As with CmnSprDrawSprite(), the real work is done in the loop; however, since
- there is an offset from the bottom of the workspace, the code is slightly
- different than the previous loop.
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4.4. New Functions ΓòÉΓòÉΓòÉ
-
- New Functions
-
- So, now we have this fancy capability in our library, but we have no way of
- changing the z-order of a sprite once it has been established (save removing
- all of the sprites from the playing and re-adding them in the desired order).
- To alleviate this, two new functions were added which simply operate on the
- ahsSprites array of the playground. The code is presented below but will not
- be discussed.
-
- SPRERROR EXPENTRY CmnSprSetLayering(HPS hpsDraw,HCSSPRITE hsSprite,LONG lPos)
- //-------------------------------------------------------------------------
- // This function sets the z-order of a sprite.
- //
- // Input: hpsDraw - handle to the HPS to make the updates in.
- // hsSprite - handle to the sprite whose z-order is to be changed
- // lPos - an absolute layer number (0 to MAX_SPRITES-1) or an
- // SSL_* constant.
- // Returns: SPR_ERR_NOERROR if successful, SPR_ERR_* constant otherwise
- //-------------------------------------------------------------------------
- {
- USHORT usSemAction;
- SPRERROR seError;
- LONG lOld;
- LONG lNew;
- LONG lOldDx;
- LONG lNewDx;
- HCSSPRITE ahsCopy[MAX_SPRITES];
- ULONG ulIndex;
-
- if (queryHandle(hsSprite)!=QH_HCSSPRITE) {
- return SPR_ERR_BADHANDLE;
- } /* endif */
-
- usSemAction=accessSem((PCMNHANDLE)hsSprite,ACCSEM_SET);
-
- if (hsSprite->hpgPlay==NULL) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_HASNOPLAYGROUND;
- } /* endif */
-
- seError=CmnSprQueryLayering(hsSprite,&lOld);
- if (seError!=SPR_ERR_NOERROR) {
- return seError;
- } /* endif */
-
- lNew=lOld;
-
- switch (lPos) {
- case SSL_TOP:
- lNew=hsSprite->hpgPlay->ulNumMembers-1;
- break;
- case SSL_BOTTOM:
- lNew=0;
- break;
- case SSL_UP:
- lNew=lOld+1;
- break;
- case SSL_DOWN:
- lNew=lOld-1;
- break;
- default:
- lNew=lPos;
- } /* endswitch */
-
- if ((lNew<0) || (lNew>hsSprite->hpgPlay->ulNumMembers-1)) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_BADLAYER;
- } /* endif */
-
- if ((lNew==lOld) || (hsSprite->hpgPlay->ulNumMembers==1)) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOERROR;
- } /* endif */
-
- memset(ahsCopy,0,sizeof(ahsCopy));
- ahsCopy[lNew]=hsSprite->hpgPlay->ahsSprites[lOld];
-
- lOldDx=0;
- lNewDx=0;
-
- for (ulIndex=0; ulIndex<hsSprite->hpgPlay->ulNumMembers-1; ulIndex++) {
- if (ulIndex==lOld) {
- lOldDx=1;
- } else
- if (ulIndex==lNew) {
- lNewDx=1;
- } /* endif */
-
- ahsCopy[ulIndex+lNewDx]=hsSprite->hpgPlay->ahsSprites[ulIndex+lOldDx];
- } /* endfor */
-
- memcpy(hsSprite->hpgPlay->ahsSprites,ahsCopy,sizeof(ahsCopy));
-
- CmnSprDrawSprite(hpsDraw,hsSprite);
-
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOERROR;
- }
-
- SPRERROR EXPENTRY CmnSprQueryLayering(HCSSPRITE hsSprite,PLONG plPos)
- //-------------------------------------------------------------------------
- // This function sets the z-order of a sprite.
- //
- // Input: hsSprite - handle to the sprite whose z-order is to be queried
- // plPos - points to the variable to receive the layer number.
- // Output: plPos - points to the layer number (0 to MAX_SPRITES-1).
- // Returns: SPR_ERR_NOERROR if successful, SPR_ERR_* constant otherwise
- //-------------------------------------------------------------------------
- {
- USHORT usSemAction;
- ULONG ulIndex;
-
- if (queryHandle(hsSprite)!=QH_HCSSPRITE) {
- return SPR_ERR_BADHANDLE;
- } /* endif */
-
- usSemAction=accessSem((PCMNHANDLE)hsSprite,ACCSEM_SET);
-
- if (hsSprite->hpgPlay==NULL) {
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_HASNOPLAYGROUND;
- } /* endif */
-
- for (ulIndex=0; ulIndex<hsSprite->hpgPlay->ulNumMembers; ulIndex++) {
- if (hsSprite->hpgPlay->ahsSprites[ulIndex]==hsSprite) {
- *plPos=ulIndex;
- return SPR_ERR_NOERROR;
- } /* endif */
- } /* endfor */
-
- accessSem((PCMNHANDLE)hsSprite,usSemAction);
- return SPR_ERR_NOTFOUND;
- }
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4.5. Collision Detection ΓòÉΓòÉΓòÉ
-
- Collision Detection
-
- (This section describes the concepts of collision detection, although no code
- has yet been written to implement this.)
-
- Collision detection, a necessary function in most video games, is the method by
- which it is determined if two objects are touching at any point. Consider the
- following two sprites:
-
- It is obvious that this is far more complicated a matter than simply checking
- the bounding rectangles, since the object drawn within will probably not
- encompass the entire bounding rectangle, nor will they be as regularly shaped
- as the examples above.
-
- Et Tu, Brute?
-
- As in most Computer Science problems, brute force could be applied here to
- solve this problem:
-
- 1. If the bounding rectangles do not overlap, then the test fails.
-
- 2. Calculate the union of the bounding rectangles
-
- 3. For each pel in the union rectangle, check each sprite to see if it has a
- pel in that position also. If we find one, the test succeeds.
-
- 4. The test fails if we reach this point.
-
- While this algorithm would probably work, the performance is O(n*n), which is
- unacceptable for programs - such as video games - where pseudo-real-time
- response is necessary. However, this approach is not entirely without its
- merits...
-
- Consider step 3 in the pseudo-code above, since that is the performance-eater.
- If we could reduce the CPU requirements of this step to below some threshold
- that we define, the algorithm becomes quite usable. Since the problem lies in
- our double-loop plus system call, that should be our area of concentration.
-
- The first step in solving this is to figure out how we would implement the step
- in its unmodified state. The only fault-proof way that I could think of was to
- use the masks of each sprite, since they are not contaminated by the background
- bitmap. By adjusting our indices to allow for offsets of each mask relative to
- the positions of the corresponding sprites, we can easily determine if the
- sprite has a pel at any given position or not.
-
- Some of you might already see the solution.
-
- Using the monochrome property of the masks, we could speed up this algorithm
- considerable if we call GpiBitBlt() to copy each of the masks into a workspace
- and then check for the intersection of the two (black pels, if you do not
- remember. See the first article in this series.). However, the double loop
- still keeps the performance at O(n*n), although the prefixing coefficient is no
- longer as large.
-
- The final step is to convert this to a linear operation, instead of a
- two-dimensional one. This is done by calling GpiQueryBitmapBits() and then
- using memchr() to search for any byte that is non-255. (If you don 't
- understand that, remember that we have a monochrome bitmap, so each white pel
- is represented by a set bit. All white therefore equates to 255, but we are
- looking for a single black pel.) Since monochrome bitmaps take very little
- memory and since the library has an inherent maximum size for sprites, we can
- allocate the memory to hold the bitmap bits during the CmnSprCreatePlayground()
- call and use the workspace that we are already allocating (hpsWork) for the
- GpiBitBlt() call.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- If you are impatient, you can code this before I do. <grin>
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 4.6. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- In this final article, we looked at how z-ordering can and is implemented in
- our sprite library. If you get version 1.6.0 of the Common/2 library (now on
- ftp.cdrom.com) and compile the included I-495 sample to use this library, you
- will find that the performance does not suffer noticably.
-
- Additionally, we looked into collision detection and how it could be
- implemented with maximum performance; this will undoubtedly be added to a
- future version of Common/2 to ease the burden of those inspired writers who
- wish to translate their favorite "shoot-em up" game to their favorite operating
- system.
-
- Sprites and Animation (Reprise) - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5. /dev/EDM/BookReview ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 5.1. Introduction ΓòÉΓòÉΓòÉ
-
- /dev/EDM2/BookReview
-
- Written by Carsten Whimster
-
- Introduction
-
- /dev/EDM2/BookReview is a monthly column which focuses on development oriented
- books and materials. The column is from a beginning PM programmer's eyes,
- because that's what I am. Pick up whichever book strikes your fancy, and join
- the growing group of people following our PM programming columns. I will
- review books aimed at beginners for a while, and then move on from there.
-
- Please send me your comments and thoughts so that I can make this column as
- effective as possible. All mail to me gets read and responded to.
-
- Mastering OS/2 REXX is an introductory REXX programming book. It assumes little
- or no previous programming knowledge.
-
- /dev/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5.2. Errata ΓòÉΓòÉΓòÉ
-
- Errata
-
- I have been working a bit more on my OS/2 WWW page, but I need a more permanent
- place to put it, as I have to pay for the current location separately, so you
- won't see it advertized any more, until I find a new spot :)
-
- It has been quiet with respect to mail from readers again. It would be nice if
- more readers would take the time to send in their thoughts and comments, both
- positive and negative, but then we are all busy.
-
- Watcom C/C++ 10.0 is here. It looks really good, but I haven't had the time to
- look closer yet. It came in a package the size of a hard-cover book,
- containing only the CD-ROM (in case you hadn't guessed that I chose this
- format), a "Getting Started" booklet, and some flyers. The complete
- documentation package can be had for around $100 as an update (to 9.5), or $150
- for the whole deal. I decided to live with the on-line version for now, as the
- price for the documentation is the same whether you buy it right away or not.
-
- /dev/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5.3. Mastering OS/2 REXX ΓòÉΓòÉΓòÉ
-
- Mastering OS/2 REXX
-
- Mastering OS/2 REXX is a how-to book on REXX programming for rank novices. It
- does a lot of hand-holding along the way, and is very unintimidating. It is
- aimed squarely at people who have either never programmed, or have programmed
- very little. It introduces new concepts with great patience, and has many
- little sample programs to illustrate key concepts and functionality. The
- following are the chapters:
-
- 1. What You Can Do With REXX
- 2. Where Does REXX Fit in on OS/2?
- 3. How to Create and Execute a REXX Program
- 4. REXX Syntax: The Rules of the Language
- 5. The Basics: Some Simple REXX Verbs
- 6. IF - the Conditional
- 7. String Manipulation: The Parse Instruction
- 8. Debugging
- 9. Trapping Errors
- 10. Math
- 11. SELECT: The Case Structure
- 12. Executing OS/2 Commands
- 13. Built-in Functions
- 14. User-Written Functions/Subroutines
- 15. Looping
- 16. Queueing Data with REXX
- 17. Compound Variables
- 18. Reading and Writing Files
- 19. The INTERPRET Instruction
- 20. Converting from Batch Files
- 21. Appendix A: Problems and Solutions
- 22. Appendix B: OS/2 Commands
- 23. Appendix C: REXX Instructions
- 24. Appendix D: REXX Functions
- 25. Appendix E: REXX Reserved Variables
-
- The first two chapters are very introductory in nature, and only describe
- briefly what can be done with REXX, and how REXX is accessed on OS/2.
-
- Chapter 3 introduces REXX properly, and eventually introduces the first little
- snippet of REXX code, but first it describes in (excrutiating, for those of us
- familiar with EPM and WPS) detail what shadows are, how to make a directory for
- your programs, how to start the editor (EPM), a brief tutorial on EPM, how to
- run your REXX programs on the commandline, and how to use PMREXX to run your
- REXX programs in the WPS environment. It also shows how to tell where your
- program is being executed, from within your program. Tokenizing of a program is
- demonstrated as well. Although this all sounds terribly slow for the
- experienced user, it surprises you a little from time to time with unexpected
- nuggets of obscure information.
-
- Chapter 3 was only a brief demonstration, and in chapter 4 the syntax and some
- of REXX's peculiarities are explained. Numbers, literals, and variables are
- introduced, and some of the more basic keywords of REXX as well. Chapter 5
- introduces SAY, PULL, ARG, ECHO, and EXIT. By the way, each chapter is fairly
- short (with a couple of exceptions), and at the end there is a question
- section, with the answers at the back of the book. This really helps the
- novice to test his or her newly gained knowledge at an early stage, and
- reinforces the material well.
-
- Chapter 6 explains the various uses of IF, including using NOP, comparisons,
- fuzzy comparisons, and boolean operators.
-
- Chapter 7 is more difficult, and introduces the PARSE instruction. This chapter
- is not as easy as what came before, and Gargiulo is very careful not to lose
- his reader. Many of the numerous permutations of the PARSE instruction are
- demonstrated. I suspect Gargiulo has extensive experience teaching REXX,
- something which is supported by his claim to offer several REXX-based courses
- on various operating systems.
-
- Chapter 8 gets a little deeper, and introduces debugging. Both interactive
- debugging, and tracing is shown. In the same vein, chapter 9 continues the
- trouble-shooting thread into the trapping of errors. Many types of errors are
- eplained, along with the trapping techniques required to handle them.
-
- Chapter 10 leaves trouble-shooting behind, and introduces math under REXX. REXX
- is particularly flexible in math, and you can have any precision you desire.
- Precision and rounding are explained, and how to display numbers.
-
- Just a quick note here: many of the preceding chapters were very short, and
- although every new topic is accompanied by an example, it would be nice to see
- some more elaborate examples from time to time. This would enable the novice
- programmer to get a better feel for what the various constructs and
- instructions are used for in the real world, and not just the typical half-page
- programs used more or less through-out the book.
-
- Chapter 11 is dedicated to the SELECT structure, and again, this chapter is
- relatively short, although four examples were used to demonstrate the use. This
- all just goes to show that this book is for novice programmers, but doesn't
- teach programming, only REXX.
-
- Executing OS/2 commands is the topic of chapter 12, and REXX's built-in
- functions are in chapter 13. Passing parameters is explained in more detail,
- and how to do this with OS/2 commands is explained. A good-sized list of
- available REXX functions is given. The list is well organized into categories
- to help dissipate the unavoidable confusion when confronted with a slew of new
- functions in one go. Many of these functions will have to be tried, or looked
- up in the on-line reference before the meaning becomes clear, but after the
- list, the more important ones are explained in more detail. The logical
- follow-up to chapter 13 is given in chapter 14, User-written
- Functions/Subroutines. This chapter shows how to use the RESULT variable,
- parameter passing and parsing, the RETURN keyword, labels, how to avoid sharing
- variables, and then compares internal and external REXX functions. Some
- pointers are given on style too, something which the book in general only shows
- through the snippets.
-
- Chapter 15 shows the many types of loops available in REXX, and tries to
- explain where to use the different kinds. This is explained mainly through
- showing the constraints of each kind, and the higher level theory of the use of
- the different kinds is skipped over. Again, style and actual programming isn't
- really taught that much here, only REXX. From time to time there is a little
- something, but not much.
-
- Chapter 16 surprised me a bit. Queueing is not a basic concept, yet Gargiulo
- teaches it with the same thoroughness that he teaches the simpler concepts.
- Simple process-to-process communication is explained, but not the need for it.
- The novice must be scratching his or her head at this point, saying "ok, but
- why?". The answer: look elsewhere for a why, this is a REXX how-to.
-
- Compund variables are treated rather late in chapter 17, but the possible
- real-world use is skipped again.
-
- File input and output is introduced in chapter 18, including reading from and
- writing to COM ports, the keyboard, printers, and the STD file streams, STDIN,
- STDOUT, and STDERR.
-
- Chapter 19 demonstrates the INTERPRET instruction in three pages (now you know
- why many of the preceding paragraphs don't seem to say much more than the title
- of the chapters).
-
- Finally, the book is wrapped up in chapter 20 by explaining how to convert from
- batch files to REXX programs, and when this is desirable.
-
- /dev/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5.4. Summary ΓòÉΓòÉΓòÉ
-
- Summary
-
- This book is very slow-moving, and is not aimed at anyone reasonably familiar
- with any modern programming language. It is very tutorial in nature, and
- introduces only the most basic concepts most of the time. The various looping
- constructs and so on are all explained as if you have never seen them before in
- any language. The verbal language used by Gargiulo is also very tutorial, as
- opposed to informational. This leaves me wondering why he skipped the
- high-level explanations of programming. Usually, introductory books aim to
- teach programming, and then choose a language to do it. It almost seems as if
- this book aims only to teach REXX, and not programming. I cannot imagine what
- kind of person would know how to program, but not be familiar with any actual
- language? In any case, the book teaches REXX very thoroughly, and it does
- hand-hold you through some slightly intermediate concepts. I have no problem
- recommending this book to bright would-be programmers, but I might hesitate a
- little before recommending it to someone whose computer knowledge is a little
- more sparse.
-
- /dev/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5.5. Books Reviewed ΓòÉΓòÉΓòÉ
-
- Books Reviewed
-
- This table contains all books I have reviewed, so that you can find what you
- are looking for at a glance. I will be careful to rate books fairly. If I
- feel a need to adjust ratings, I will adjust all of them at the same time, and
- write a note explaining why I felt this necessary. 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.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéBOOK ΓöéAUDIENCE ΓöéMARKΓöéCOMMENTS Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéReal-World Programming for OS/2 2.1,ΓöéIntermediateΓöéB+ ΓöéLots of good code examples, but sometimes it is Γöé
- ΓöéBlain, Delimon, and English, SAMS Γöéto Advanced Γöé Γöétoo complex for novices. Accurate. Well Γöé
- ΓöéPublishing. ISBN 0-672-30300-0. ΓöéPM C Γöé Γöéorganized. The index needs a little beefing up. Γöé
- ΓöéUS$40, CAN$50. Γöéprogrammers Γöé ΓöéGood, but not entirely complete how-to reference.Γöé
- Γöé Γöé Γöé ΓöéGood purchase. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéLearning to Program OS/2 2.0 ΓöéBeginning PMΓöéB- ΓöéThis book can be both frustrating and very Γöé
- ΓöéPresentation Manager by Example, ΓöéC Γöé Γöérewarding. It is not very large, and a bit Γöé
- ΓöéKnight, Van Nostrand Reinhold. ISBNΓöéProgrammers Γöé Γöépricey, but has some excellent chapters on Γöé
- Γöé0-442-01292-6. US$40, CAN$50. Γöé Γöé Γöécertain beginning topics, such as messages, Γöé
- Γöé Γöé Γöé Γöéresources, IPF, and dialog boxes. Strictly for Γöé
- Γöé Γöé Γöé Γöébeginners. This book has only one (large) sampleΓöé
- Γöé Γöé Γöé Γöéprogram! Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéWriting OS/2 2.1 Device Drivers in ΓöéAdvanced C ΓöéA- ΓöéThe only thing a device driver programmer would Γöé
- ΓöéC, 2nd Edition, Mastrianni, Van ΓöéProgrammers,Γöé Γöénot find in here is how to write SCSI, ADD, and Γöé
- ΓöéNostrand Reinhold. ISBN Γöéfamiliar Γöé ΓöéIFS drivers. Most everything else is in here, Γöé
- Γöé0-442-01729-4. US$35, CAN$45. Γöéwith Γöé Γöéalong with skeleton examples. An optional DevHlpΓöé
- Γöé Γöéhardware Γöé Γöélibrary of C-callable functions can be purchased Γöé
- Γöé Γöéprogramming Γöé Γöéby those who don't have time to write their own. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéOS/2 Presentation Manager GPI, Winn,ΓöéIntermediateΓöéC+ ΓöéThis book needs updating for OS/2 2.x. It is a Γöé
- ΓöéVan Nostrand Reinhold. ISBN Γöéto advanced Γöé Γöéwell-written in-depth coverage of the OS/2 way ofΓöé
- Γöé0-442-00739-6. US$35, CAN$45. ΓöéPM C Γöé Γöéprogramming for graphics. It is not an Γöé
- Γöé Γöéprogrammers Γöé Γöéintroductory PM or graphics programming book. Γöé
- Γöé Γöé Γöé ΓöéYou should know the basics of PM programming Γöé
- Γöé Γöé Γöé Γöéalready. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéThe Art of OS/2 2.1 C Programming, ΓöéBeginning ΓöéB+ ΓöéThis is a great introductory PM programming book.Γöé
- ΓöéPanov, Salomon, and Panov, ΓöéOS/2 and PM Γöé ΓöéIt covers basic OS/2 issues like threads before Γöé
- ΓöéWiley-QED. ISBN 0-471-58802-4. Γöéprogrammers Γöé Γöéit jumps into PM programming. The coverage is Γöé
- ΓöéUS$40, CAN$50. Γöé Γöé Γöéquite thourough, with just enough reference Γöé
- Γöé Γöé Γöé Γöématerial to make it useful after you read it Γöé
- Γöé Γöé Γöé Γöéthrough the first time. The upcoming revised Γöé
- Γöé Γöé Γöé Γöéedition should be a killer. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMastering OS/2 REXX, Gargiulo, ΓöéIntermediateΓöéB ΓöéThis book is very easy to understand. If you Γöé
- ΓöéWiley-QED. ISBN 0-471-51901-4. ΓöéOS/2 users Γöé Γöéprogram with any regularity, look elsewhere, but Γöé
- ΓöéUS$40, CAN$50. Γöéand novice Γöé Γöéif you need an easily read, well-explained Γöé
- Γöé Γöéprogrammers Γöé Γöébeginner's book, look no further. Some more Γöé
- Γöé Γöé Γöé Γöédetailed, and complex real-world examples might Γöé
- Γöé Γöé Γöé Γöébe useful as you learn the material. Good Γöé
- Γöé Γöé Γöé Γöécoverage of REXX's capabilities. Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- LEGEND:
-
- BOOK: The name of the book, author(s), 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.
-
- ΓöîΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé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/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 5.6. Coming Up ΓòÉΓòÉΓòÉ
-
- Coming Up
-
- Next month I will be looking at REXX Reference Summary Handbook, Goran. The
- books I intend to review are (not necessarily in this order):
-
- o REXX Reference Summary Handbook, Goran
- o OS/2 Presentation Manager Programming, Petzold
- o Application Development Using OS/2 REXX, Rudd
- o The Design of OS/2, 2nd Edititon, Kogan and Deitel - 1994 - not published yet
- (or is it?)
-
- I am considering reviewing the IBM OS/2 Redbooks, since they are readily and
- cheaply available, and look like good reference.
-
- I am also considering reviewing Designing OS/2 Applications, Reich, mostly
- because it promises to present a different angle on OS/2 programming, namely
- that of how to design OS/2 applications, rather than how to program OS/2
- applications.
-
- Finally, I am considering reviewing OS/2 Unleashed, but it is not strictly
- speaking a development book, so I'm going to wait until the list of real
- development books has diminished a bit. I hear that there is a CD-ROM version
- of it out now, and I will try to get a copy of this.
-
- If anyone has a book they want to see reviewed, I will be happy to oblige as
- long as I can afford it. Of course, requests can be satisfied quicker when
- accompanied by a book :) 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/EDM/BookReview - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 6. C++ Corner ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 6.1. Introduction ΓòÉΓòÉΓòÉ
-
- C++ Corner
-
- Written by Gordon Zeglinski
-
- Introduction
-
- This column deviates from the usual C++ stuff; instead, we will be exploring
- SOM's OOP model. More precisely, the SOMobjects Developer Toolkit, which ships
- with SOM 2 and DSOM, will be examined.
-
- C++ Corner - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 6.2. What is SOM? ΓòÉΓòÉΓòÉ
-
- What is SOM?
-
- SOM, the System Object Model, is a language neutral object model. An Object in
- SOM is defined using an Interface Definition Language. The interface language
- is then "compiled" into a language specific form. For instance, if one were
- using C to implement the object, the SOM compiler would be used to produce .C,
- .IH, and .H files. The language specific form created by the SOM compiler has
- function stubs that the programmer would fill in. These stubs are the bodies
- to the member functions defined in the IDL. Because SOM objects can be used
- across different languages and compilers, they use the same linkage as OS/2's
- API and their names are not mangled like in C++.
-
- OS/2 2.11 and previous versions of OS/2 2.x use SOM 1 in the Workplace Shell
- (WPS). SOM 1 is also central to the design of VX-Rexx, and VisPro REXX. (Of
- course, any WPS based application is also SOM based.) Not too worry, SOM 1
- based applications will still run when SOM 2 is installed because SOM 2 is
- backwards compatible to SOM 1.
-
- The following list specifies some of the ways in which SOM 2 differs from SOM
- 1:
-
- 1. allows multiple inheritance
- 2. allows derived metaclasses
- 3. is CORBA compliant
- 4. methods can return structures
- 5. multiple classes can be packaged within a single file
-
- Objects in SOM can be packaged in DLLs or in EXEs. Using DLLs offers the
- greatest flexibility. In fact, this is how one can extend the WPS and the
- other SOM based programs mentioned above.
-
- DSOM
-
- DSOM (Distributed System Object Model) allows SOM objects to be manipulated
- across processes. These processes can even be on different machines. In
- theory, this could make extending the WPS much easier than it presently is. If
- the WPS is writen to use DSOM objects, then it will be posible to write WPS
- objects that can run in their own EXE and debug that EXE instead of the whole
- WPS.
-
- Note: the WARP II beta ships with SOM 2.
-
- The toolkit ships with a few goodies. The first item, called "Replication
- Frameworks", allows an object to exist in multiple processes at the same time,
- even across networks. Changes to any replicated object will be relayed to all
- replicas of the object. The network type and other details are abstracted from
- the programmer. Next is the "Persistence Frameworks"; it is used to stored
- objects on to disk. The "Event Management Frameworks" can be used to
- encapsulate event based activities, like the PM message loop.
-
- Now that we have briefly looked at some of the features in the SOM toolkit,
- we'll move on to a quick look at the SOM OOP model.
-
- C++ Corner - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 6.3. SOM OOP vs C++ OOP ΓòÉΓòÉΓòÉ
-
- SOM OOP vs C++ OPP
-
- First, let's take a quick look at how the two OOP models differ. SOM uses a
- more runtime oriented OOP model. That is, the exact function that is being
- called, or the size of the object may not be known until the code is executed.
- Methods are called using one of the following schemes:
-
- 1. Offset resolution (default)
- 2. Name-lookup resolution
- 3. Dispatch-function resolution
-
- The above list is ordered by decreasing execution speed. Offset resolution is
- similar to "virtual functions" used in C++. The name-lookup method allows a
- method whose name is not known until run-time to be called. The most flexible
- and time consuming resolution method uses the dispatch-function. This method
- allows methods to be called using application specific rules. As mentioned
- before, method names are not mangled like they are in C++; this is because,
- unlike C++, SOM does not allow operators to be overloaded.
-
- Metaclasses
-
- Coming from a C++ background, this is where things get confusing. In C++, the
- most fundamental object is a class. Class methods or data members were
- declared as "static" member of the class. This is not the case in SOM. Classes
- are instances of metaclasses, and objects are instances of classes. The
- metaclass contains all the class specific functions and data. Roughly
- speaking, a metaclass can contain data and methods that were either explicitly
- of implicitly defined as being static in C++.
-
- Note: constructors are implicitly static member functions in C++.
-
- C++ Corner - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 6.4. A Simple Example ΓòÉΓòÉΓòÉ
-
- A Simple Example
-
- We'll take the "Hello World" example created by IBM and add some class data and
- methods to it. The source code presented here will have the IBM disclaimers
- stripped, if you really want to read them, see the source code files. We start
- by looking at HELLO.IDL.
-
- #ifndef hello_h
- #define hello_h
-
- #include <somcls.idl>
-
- interface M_Hello;
- interface Hello : SOMObject
- {
- string hello_();
- attribute string hellomsg;
-
- void sayHello();
-
- #ifdef __SOMIDL__
- implementation
- {
- releaseorder: hello_, _get_hellomsg, _set_hellomsg,sayHello;
- callstyle=oidl;
- filestem = hello;
- metaclass = M_Hello;
- somInit: override;
- };
- #endif /* __SOMIDL__ */
- };
-
- interface M_Hello : SOMClass
- {
- attribute string ClassData;
-
- Hello HelloCreate(in string msg);
- // This method creates an instance of the Hello class and
- // uses the value of "msg" to initialise it.
- #ifdef __SOMIDL__
- implementation
- {
- releaseorder: HelloCreate,_get_ClassData,_set_ClassData;
- callstyle=oidl;
- filestem = hello;
- functionprefix=M_;
- somInitMIClass: override;
- somInit: override; // just a test for parent call macros
- };
- #endif /* __SOMIDL__ */
- };
-
- #endif /* hello_h */
-
- To the Hello class, I have added the member void sayHello(). To the M_Hello
- metaclass, I have added the member attribute string ClassData. An attribute is
- merely a data member that has _get_ and _set_ methods automatically defined for
- it. The original code can be found in the \som\samples\somk\cpp\derived
- directory if the samples were installed with the toolkit. The code for
- sayHello() is shown below. This code illustrates how to access instance data
- and class data. The code below is written using the C++ bindings.
-
- SOM_Scope void SOMLINK sayHello(Hello *somSelf)
- {
- //the folowing two lines are created by the som compiler.
- HelloData *somThis = HelloGetData(somSelf);
- HelloMethodDebug("Hello","sayHello");
-
- // Get the CLASS instance
- M_Hello *helloCls=(M_Hello *)somSelf->somGetClass();
-
- printf("%s an instance of %s\n",somSelf->_get_hellomsg(),helloCls->_get_ClassData());
- }
-
- It is worth noting that the data/attributes are accessed by calling methods
- rather than by explicitly using the attributes name. Also, class data is
- accessed by using a pointer to an instance of the M_Hello metaclass.
-
- Note: M_Hello is the metaclass for Hello.
-
- Now lets put this code to work.
-
-
- int main(int argc, char *argv[])
- {
- Hello *a,*b,*c;
-
- // create an instance of the M_Hello metaclass
- M_Hello *helloClsObj=HelloNewClass(Hello_MajorVersion,Hello_MinorVersion);
-
- //set the class data
- helloClsObj->_set_ClassData("Class 1");
-
- //call the M_Hello class method HelloCreate to create an instance of
- //the class Hello
-
- a=helloClsObj->HelloCreate("Hello from A");
- b=helloClsObj->HelloCreate("Hello from B");
- c=helloClsObj->HelloCreate("Hello from C");
-
- //call the sayHello method for each object
- a->sayHello();
- b->sayHello();
- c->sayHello();
-
- // free up each of the objects
- a->somFree();
- b->somFree();
- c->somFree();
-
- return 0;
- }
-
- C++ Corner - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 6.5. Wrapping Things Up ΓòÉΓòÉΓòÉ
-
- Wrapping Things Up
-
- We briefly looked at some of the components of the SOMobjects Developers
- Toolkit. In adition a simple SOM 2 example was presented. In the next issue,
- we will look at creating a SOM class that encapsulates the INI interface.
-
- C++ Corner - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 7. Introduction to PM Programming ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 7.1. Introduction ΓòÉΓòÉΓòÉ
-
- Introduction to PM Programming
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- The purpose of this column is to provide the readers out there who are not
- familiar with PM application development the information necessary to satisfy
- their curiousity, educate themselves, and give them an advantage over the
- documentation supplied by IBM. Of course, much of this stuff could probably be
- found in one of the many books out there, but the problem with books in general
- is that they don't answer the questions you have after you read the book the
- first time through.
-
- I will gladly entertain feedback from the readers about what was "glossed over"
- or what was detailed well, what tangential topics need to be covered and what
- superfluous crap should have been removed. This feedback is essential in
- guaranteeing that you get what you pay for. :)
-
- It should be said that you must not depend solely on this column to teach you
- how to develop PM applications; instead, this should be viewed as a supplement
- to your other information storehouses (books, the network conferences, etc.).
- Because this column must take a general approach, there will be some topics
- that you would like to see discussed that really do not belong here. Specific
- questions can be directed to the Scratch Patch, where an attempt to answer them
- will be made.
-
- Last Month
-
- Last month, we began looking at the WC_LISTBOX window class, how it is used,
- what its limitations are, and some of the messages associated with it. We
- resume this track this month, and take another look at nameDlgProc() in HELLO.C
- (see intro.zip).
-
- Introduction to PM Programming - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 7.2. nameDlgProc() and Listboxes ΓòÉΓòÉΓòÉ
-
- nameDlgProc() and Listboxes
-
- If you'll look at HELLO.C, you will see comments to the right of the source
- code of the form "@n", where n is a number. These are landmarks that are
- referenced, so if you don't have the source handy, please make it available.
- Our first one is...
-
- Macros
-
- landmark number 7.
-
- WinInsertLboxItem(hwndLb,LIT_END,achText); // @7
-
- This line, while it looks like a function call, is a macro defined in the
- Programmer's Toolkit. This macro expands to:
-
- #define WinInsertLboxItem(hwndLbox, index, psz) \
- ((LONG)WinSendMsg(hwndLbox, LM_INSERTITEM, MPFROMLONG(index), \
- MPFROMP(psz)))
-
- There are two points to this: 1) there are handy macros which can shorten
- your coding time if you know what they are, and 2) this function call is really
- nothing more than the sending of an LM_INSERTITEM message, which we looked at
- briefly last month.
-
- Now, find numbers...
-
- Notifications
-
- 8 and 9. This is a notification sent to the owner of the listbox - the dialog
- - via the WM_CONTROL message.
-
- case WM_CONTROL: // @8
- switch (SHORT1FROMMP(mpParm1)) {
- case DNAME_LB_NAMELIST:
- switch (SHORT2FROMMP(mpParm1)) {
- case LN_SELECT: // @9
- {
- HWND hwndLb;
- SHORT sIndex;
-
- hwndLb=WinWindowFromID(hwndWnd,DNAME_LB_NAMELIST);
-
- sIndex=WinQueryLboxSelectedItem(hwndLb);
- WinQueryLboxItemText(hwndLb,
- sIndex,
- pndiInfo->achName,
- sizeof(pndiInfo->achName));
-
- WinSetDlgItemText(hwndWnd,
- DNAME_EF_NAME,
- pndiInfo->achName);
- }
- break;
-
- The notification LN_SELECT is sent to let you know that an item was selected by
- the user. This could be using the mouse or the keyboard (using the up and down
- arrows, if single-select, or the spacebar, if multi-select). It needs to be
- pointed out that the item that was selected is not passed as a parameter of the
- message, and no matter how many complaints were filed when this was noticed,
- IBM would not change it.
-
- "Big deal", you think. For single-select listboxes, this is not a problem, but
- for multi-select it is a huge problem. Consider why: you determine the
- selected item using the message LM_QUERYSELECTION which returns the first
- selected item after the index specified, or the macro WinQueryLboxItemText()
- which always searches from the beginning. However, what happens if the user
- selects one item, and then an item following the first selection? There is a
- solution to this problem, fortunately, but it will not be discussed until we
- look at ownerdraw listboxes.
-
- The next notification is at landmark 10.
-
- case LN_ENTER: // @10
- WinPostMsg(hwndWnd,WM_COMMAND,MPFROMSHORT(DID_OK),0);
- break;
-
- This notification comes whenever the user double-clicks on an item in the
- listbox or presses the ENTER key while the listbox has the input focus. As
- with the LN_SELECT notification, this has its shortcomings. The first is the
- same as the last notification - finding out which item was selected in a
- multi-select listbox. The second occurs whenever you have a default pushbutton
- and the user presses the ENTER key (vs. double-clicking, which doesn't have
- this problem). A default pushbutton is one the acts as though it was selected
- if the user presses ENTER and the window with the input focus is not a
- pushbutton. In this scenario, you receive both the LN_ENTER notification and
- the WM_COMMAND message (which is sent by the pushbutton). Unfortunately, there
- is no good solution to this problem other than to avoid placing yourself in
- this situation.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
-
- We are slowly, but surely, making progress in dissecting HELLO.C. We will
- return for the last time when we have looked at buttons, but I suspect that by
- now you have already figured out the rest of the program.
-
- Introduction to PM Programming - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 7.3. More Messages ΓòÉΓòÉΓòÉ
-
- More Messages
-
- Let's look at more of the common messages used by the listbox. Unlike the
- entryfield, we will not examine all of the listbox messages, nor all of the
- messages of any future controls we will look at. This is because, with few
- exceptions, each control has so many messages that it would quickly become a
- hinderance to this column's effectiveness.
-
- LM_DELETEITEM
-
- This message is sent to delete an item from the listbox.
-
- Parameters
-
- param1
-
- lIndex (LONG)
-
- 0-based index of the item to be deleted.
-
- param2
-
- ulReserved (ULONG)
-
- Reserved, 0.
-
- Returns
-
- reply
-
- bSuccess (BOOL)
-
- TRUE successful completion
- FALSE error occurred
-
- LM_DELETEALL
-
- This message is sent to delete all items from the listbox.
-
- Parameters
-
- param1
-
- ulReserved (ULONG)
-
- Reserved, 0.
-
- param2
-
- ulReserved (ULONG)
-
- Reserved, 0.
-
- Returns
-
- reply
-
- bSuccess (BOOL)
-
- TRUE successful completion
- FALSE error occurred
-
- Introduction to PM Programming - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 7.4. Notes and Next Month ΓòÉΓòÉΓòÉ
-
- Notes and Next Month
-
- I do apologize for the snail's pace being taken in this column, but I do not
- want to overwhelm anyone by presenting too much information. I have received
- little feedback and even though it was positive, the ether is too silent for me
- to think that I am doing everything correctly. Please send me your comments
- about this column and any questions you might have about topics that I
- delicately skirt.
-
- Next month, we will begin looking at the WC_BUTTON class, specifically the
- pushbutton, and also will look at the ownerdraw window from both a listbox and
- a pushbutton perspective.
-
- Introduction to PM Programming - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 8. Scratch Patch ΓòÉΓòÉΓòÉ
-
-
- ΓòÉΓòÉΓòÉ 8.1. Introduction ΓòÉΓòÉΓòÉ
-
- Scratch Patch
-
- Written by Larry Salomon, Jr.
-
- Introduction
-
- Welcome to this month's "Scratch Patch"! Each month, I collect various items
- that fit into this column sent to me via email. The ones that I feel contribute
- the most to developers, whether in terms of information or as a nifty trick to
- tuck into your cap, get published in this column.
-
- To submit an item, send it via email to my address - os2man@panix.com - and be
- sure to grant permission to publish it (those that forget will not be
- considered for publication).
-
- Scratch Patch - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 8.2. Gotcha Notes! ΓòÉΓòÉΓòÉ
-
- Gotcha Notes!
-
- It appears that if you have the following:
-
- DosOpen("A:",...)
-
- do {
- DosDevIOCtl(...,IOCTL_GETDEVICEPARAMS,...)
-
- ulSzDestDrive= ... ;
-
- if (ulSzSourceDrive!=ulSzDestDrive) promptUser(...);
- } while (ulSzSourceDrive!=ulSzDestDrive);
-
- If the user removes the diskette when prompted, the next call to DosDevIOCtl()
- will return ERROR_NOT_DOS_DISK even though the diskette is formatted. The way
- around this is to close the drive and reopen using DosOpen().
-
- Scratch Patch - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 8.3. Questions and Answers ΓòÉΓòÉΓòÉ
-
- Questions and Answers
-
- James P Robertson (robertso@ecn.purdue.edu) writes:
-
- I was just wondering if there was an easy way to have a "tool bar". A menu of
- buttons underneath the standard system menu. I looked into value set controls,
- but I don't think that is what I am looking for. It seems as though quite a
- few applications have this tool bar.
-
- Good question, with a complex answer. There are actually two approaches to
- this problem:
-
- 1. You can create the tool bar on top of your client. This has the advantage
- of simplicity, but you must insure that the client never overlaps the tool
- bar in the z-order.
-
- 2. You can create the tool bar as another frame control. This has the
- advantage of being cleaner, but it is more difficult to do correctly.
-
- To implement the first solution, you need to do a trick that was used by many
- wallpaper programs before better techniques were developed. Intercept the
- WM_PAINT message in your client window procedure as always, but just before
- exiting the window procedure, call WinSetWindowPos() to change the z-order to
- HWND_BOTTOM.
-
- The second solution requires a bit more coding and lot more patience and
- involves a couple of steps.
-
- 1. Subclass the frame and intercept the WM_QUERYFRAMECTLCOUNT and
- WM_FORMATFRAME.
- 2. For the former message, call the old frame window procedure, add 1 to the
- result, and return this value. This message is sent to query the number of
- frame controls (system menu, titlebar, etc.). The "+1" is for the tool
- bar.
- 3. For the latter message, call the old frame window procedure, loop through
- the array of SWP structures passed in mpParm1 and adjust the value of the
- client window accordingly. Use WinQueryWindowUShort() on the hwnd field of
- the SWP structure and look for FID_CLIENT.
- 4. Insert your SWP values as the last item in the array.
-
- That should do it, but be patient. The second method isn't exactly
- well-documented anywhere and there are snags which I have undoubtedly
- forgotten.
-
- Scratch Patch - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 8.4. Snippet(s) of the Month ΓòÉΓòÉΓòÉ
-
- Snippet(s) of the Month
-
- Another, from my "library" of interesting functions which I use frequently. It
- can be found in scratch.zip.
-
- #include <os2.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- SHORT EXPENTRY writeBinaryData(FILE *pfFile,PVOID pvBuf,USHORT usSzBuf)
- //-------------------------------------------------------------------------
- // This function writes the binary data in hexadecimal/ASCII format (a la
- // Norton's disk editor) to the specified file.
- //
- // Input: pfFile - points to the FILE structure
- // pvBuf - points to the data to be written
- // usSzBuf - specifies the size of the buffer pointed to by pvBuf
- // Returns: number of characters written if successful, -1 otherwise
- //-------------------------------------------------------------------------
- {
- USHORT usOffset;
- CHAR achChars[32];
- USHORT usLine;
-
- for (usOffset=0; usOffset<usSzBuf; usOffset+=16) {
- memset(achChars,0,sizeof(achChars));
- fprintf(pfFile," ");
-
- for (usLine=usOffset; usLine<usOffset+16; usLine++) {
- if (usLine<usSzBuf) {
- fprintf(pfFile,"%02X ",((PBYTE)pvBuf)[usLine]);
-
- if (isprint(((PCHAR)pvBuf)[usLine])) {
- achChars[usLine-usOffset]=((PCHAR)pvBuf)[usLine];
- } else {
- achChars[usLine-usOffset]='.';
- } /* endif */
- } else {
- fprintf(pfFile," ");
- achChars[usLine-usOffset]=' ';
- } /* endif */
- } /* endfor */
-
- fprintf(pfFile,"| %s\n",achChars);
- } /* endfor */
-
- fflush(pfFile);
- return usSzBuf;
- }
-
- Scratch Patch - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 8.5. Want Ads ΓòÉΓòÉΓòÉ
-
- Want Ads
-
- Below are the hot topics as of this issue's writing. Feel free to write on any
- of these.
-
- Workplace Shell Programming (hot) - given that Taligent has released a beta
- version of the application frameworks, we should all be scrambling to learn how
- to program WPS objects so that we can leapfrog into the next generation of
- operating systems when the technology is completely subsumed by current
- systems.
-
- Client/Server (hot) - using either named pipes (with or without a network) or
- sockets, client/server programming is all the rage these days. On a related
- note, some people have also expressed an interest in learning about interfacing
- with the various protocol drivers (e.g. NDIS, IPX/SPX, etc.). Any articles in
- this area are most welcome.
-
- Multimedia (warm) - we recently had two articles on this topic. However, they
- both dealt with sound, which we all know is not the only alternative media
- type. Articles on anything else - MIDI, video, etc. - are needed.
-
- Graphics (warm) - using the Gpi is a complicated topic which can easily sport a
- number of articles (correlations, transformations, etc.). I'm sure that this
- would be well received by the readers.
-
- Scratch Patch - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9. 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 ftp.cdrom.com in the /pub/os2/2_x/program/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:
-
- o Larry Salomon - os2man@panix.com (Internet).
- o Carsten Whimster - bcrwhims@undergrad.math.uwaterloo.ca (Internet).
-
- The following people contributed to this issue in one form or another (in
- alphabetical order):
-
- o Frank Matthijs
- o Larry Salomon, Jr.
- o Carsten Whimster
- o Gordon Zeglinski
- o Network distributors
-
- Contributors - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9.1. Frank Matthijs ΓòÉΓòÉΓòÉ
-
- Frank Matthijs
-
- Frank Matthijs received his Master's degree in Civil Engineering, Computer
- Science at the Katholieke Universiteit Leuven (Catholic University of Louvain,
- Belgium). He is currently a PhD student at the same university, researching
- Input/Output frameworks for parallel/distributed systems. He started
- programming in DOS using Pascal and Assembler, started using and programming
- OS/2 since version 2.0 and now uses C and C++ almost exclusively.
-
- He can be reached electronically on the Internet as
- Frank.Matthijs@cs.kuleuven.ac.be or frankm@cs.kuleuven.ac.be. You may contact
- him for any reason.
-
- He can also be reached at the following address:
-
- Frank Matthijs
- Windekindstraat 6
- 1850 Grimbergen
- Belgium
-
- Contributors - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
-
- Larry Salomon, Jr.
-
- Larry Salomon, Jr. wrote his first Presentation Manager application for OS/2
- version 1.1 in 1989. Since that time, he has written numerous VIO and PM
- applications, including the Scramble applet included with OS/2 and the
- I-Brow/Magnify/Screen Capture trio being distributed by IBM with the
- Professional Developers Kit CD-ROM. Currently, he works for Cheyenne Software
- in Roslyn, New York and resides in Bellerose, New York with his wife Lisa.
-
- Larry can be reached electronically via the Internet at os2man@panix.com.
-
- Contributors - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9.3. Carsten Whimster ΓòÉΓòÉΓòÉ
-
- Carsten Whimster
-
- Carsten is an undergraduate Computer Science student at the University of
- Waterloo, and an huge OS/2 enthusiast as of OS/2 2.0. Currently, he is using
- OS/2 2.11 GA, and is waiting for the Warp II CD-ROM.
-
- He is currently in his third year, taking operating system, language, compiler,
- and graphics courses and enjoying it. This fall he is working at the
- University of Waterloo as a tutor (course assistant) for CS241, an introductory
- course to compilers.
-
- Carsten is a beginning OS/2 PM programmer with a few projects on the go, and
- many more in his head. He uses Watcom C/C++ 10.0, Watcom VX-REXX 2.0b, and
- occasionally emx08h with gcc 2.5.7. Carsten is also a TEAM-OS/2 member.
-
- Carsten is the author of POVPanel, a shareware dashboard-like front-end for the
- POV-Ray 2.x compiler.
-
- You may reach Carsten...
-
- ...via email:
-
- bcrwhims@undergrad.math.uwaterloo.ca - Internet
-
- ...via snail mail (notice the changed address):
-
- Carsten Whimster
- 318 Spruce Street, front house
- Waterloo, Ontario
- Canada
- N2L 3E7
-
- Contributors - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9.4. 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 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 9.5. 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!
-
- o Paul Hethmon (hethmon@apac.ag.utk.edu) - Compuserve
- o Gess Shankar (gess@knex.mind.org) - Internet
- o David Singer (singer@almaden.ibm.com) - IBM Internal
- o Andre Asselin (ASSELIN AT RALVM12) - IBM Internal
-
- 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 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ 10. 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
-
- o All back issues are available via anonymous FTP from the following sites:
-
- - ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory.
- - ftp.luth.se in the /pub/os2/programming/newsletter directory.
- - generalhq.pc.cc.cmu.edu
-
- o 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.
- o 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
-
- o 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".
- o IBM's REQUEST command on all internal VM systems. Enter the VM command
- REQUEST LIST FROM ASSELIN AT RALVM12 and a list of the requestable packages
- will be sent to you; in this list are the names of the packages containing
- the EDM/2 issues.
-
- How do I Get EDM/2? - EDM/2 - Sept 1994 - Volume 2, Issue 8
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- This is a tip.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- You must install the sample files before you can use them. To do this, unzip
- the files for this article and type the following at any OS/2 prompt (in the
- directory where you unzipped the files):
-
- WPS INSTALL
-
- When the program is running, you can specify a directory to install the samples
- in. This will be your working directory for compiling the sample classes. I
- suggest you assign a separate directory for this purpose.
-
- After successfully installing the files, you can use the WPS program in your
- working directory to ready the correct files for each step.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The most natural thing to do with the first version of your class would be to
- give it version number 1.0, wouldn't it?
-
- Well, don't do that, because for some reason or another, SOM doesn't like
- version numbers to be equal to zero. So you better use 1.1 as your first
- version number, because if you use zeroes, your class will not register. In
- fact, the first attempt will only complete part of the registering process,
- while the second try will complete the process (try it to see for yourself).
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- Even if you yourself don't use anything from the OS/2 API, you still have to
- include <os2.h> because most methods use types such as PSZ that are defined in
- the os2.h file. You'll get compiler errors if you don't include this file.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- Before using the makefile, you should edit it to adapt it to your system. All
- specific information is contained in the first section called Specific
- settings. There you will find the paths for the SOM compiler, the include
- files and the libraries. Please alter these to reflect your own directory
- structure.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- You may have added the current directory (.) to your libpath. Don't rely on
- this to work when registering WPS classes. The system has its own current
- directory, and this will probably not be the one your DLL is in. The result is
- the system will not be able to find your DLL and the registering process fails.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- After you've deregistered the class, you'll notice the DLL is still locked by
- the system and there still is a Datafile Deluxe template. The next time you
- reboot, the DLL will be unlocked. This is in fact very inconvenient, since you
- would have to reboot every time you want to register a new version of your
- class (you can't overwrite the old DLL when it is locked).
-
- Alas, there's not much you can do about this. However, when you manage to
- delete the template, the DLL will also be unlocked. Deleting the template is
- not as easy as it sounds, though. Fortunately, a very nice WPS class called
- Black Hole, written by Gregory Czaja, will do the job nicely. You can probably
- find this class where you found EDM/2.
-
- Note that you also have to delete all instances of the class in order to unlock
- the DLL. In summary, I suggest you delete all instances, as well as the
- template, every time you've deregistered a class. When you later change the
- code for that class, you'll have no problems copying your new DLL over the old
- one.
-
- This is the most convenient procedure I know (I used to kill PMSHELL.EXE before
- I found this one out :-) ). If you know a better way, please tell me! It's not
- so bad, after all: you have to get rid of the template yourself, anyway.
- Rebooting won't do this for you.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- Feel free to experiment with the object we have created. You can simply alter
- the resource file if you want to replace "Datafile Deluxe" with something
- else. There is one thing you should know about the way OS/2 handles types,
- however.
-
- OS/2 is very smart and can remember all types it has once known. Isn't that
- nice? Well, no! Every new type you create will be added to the list of
- available types, but you cannot simply delete types you don't need anymore,
- using standard OS/2 utilities.
-
- The available types are stored in OS2.INI under the application name
- PMWP_ASSOC_TYPE. For every possible type, this application name has a key
- name. You'll have to use an INI editor or write a REXX script to delete the
- keys you no longer need.