home *** CD-ROM | disk | FTP | other *** search
-
- ΓòÉΓòÉΓòÉ 1. Title Page ΓòÉΓòÉΓòÉ
-
- Welcome to EDM/2 - The Electronic OS/2 Developers Magazine!
- Portions copyright (c) by Steve Luzynski, Larry Salomon Jr.
- Volume 1, issue 5
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 2. Copyright Notice (and other Legal Stuff) ΓòÉΓòÉΓòÉ
-
- The editors of this electronic magazine are Steve Luzynski and 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.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 3. From the Editors ΓòÉΓòÉΓòÉ
-
- After a rather bumpy release of volume 1, issue 4, we have high hopes that
- things will go a bit smoother in the future. Things that are on the board, so
- to speak, are:
-
- Subscription service
-
- For the Internet-reachable community, we thought that it wouldn't be too
- difficult to write an auto-mailer, especially since the Unix mail program will
- accept everything necessary on the command line. Add a list of people to mail
- to, bake for 30 minutes, and voila!
-
- Unfortunately, things were not that easy; after a first attempt, a SunOS limit
- on the number of processes was reached since mail spawns a copy of sendmail and
- then exits. Tweeking the process somewhat (pun intended) yielded a
- subscription mailer script that builds the mail header with all of the
- addresses in it and calls sendmail once for each part of the file.
-
- Having verified it with a small file, we have decided to test it for the first
- time with this issue, so we are asking that you please check the (alphabetical)
- list to see if your userid is on it. If it is and you did not receive the
- magazine automagically, please send us email as soon as possible. Assuming all
- goes well, an article will be posted to comp.os.os2.programmer.misc describing
- the subscription process, so be patient. Of course, the magazine will still be
- placed on the nets as before, but adding this service will allow us to keep a
- more accurate size of our reader base as well as allow us to reach other
- networks (like MCIMail) and BBS's with Internet mail links.
-
- New look (somewhat)
-
- Beauty is in the eyes of the beholder, so we've made a few changes to the
- magazine format. Firstly, the Questions and Answers column is being revamped,
- starting with a name change. It will now be known as the Scratch Patch and
- will contain not only Questions and Answers, but also the following items:
-
- o Snippet(s) of the Month
-
- This is for those useful, modular, functions that have been written and found
- indispensable by their authors. All submissions are requested (though not
- required) to be one function whenever possible and thoroughly commented,
- including a prologue which explains the purpose and the parameters.
-
- o Documentation Chop Shop
-
- This is for documentation-related submissions dealing with inaccuracies,
- inconsistencies, and vaguries. All potential submitters should remember that
- the goal here is to correct and clarify whenever possible; so, while pointing
- out the "tar pit" is something to write about, how to grab the vine swinging
- overhead is much more helpful.
-
- o Want Ads
-
- As in the past, we always look forward to your comments. Of particular
- interest are the requests for specific topics. Since we do not pretend to
- know everyone on the Internet, any topics that look appetizing or that have
- received a number of requests will be noted in this section in hopes that
- someone reading it will be masochistic enough to want to write an article on
- one of them. Don't forget to read the Article Submission Guidelines!!!
-
- Any submissions should be received by the editors by no later than the 25th of
- the month. And as always, even though it seems redundant, please explicitly
- state your permission for us to use what you have sent.
-
- Secondly, for this and all subsequent issues, we will try to include a
- hypertext link at the end of each section which will take you to the next
- section, so you should only have to repeatedly press ENTER (with an occassional
- TAB) to read the entire magazine.
-
- Thirdly, an installation program will be included with each issue, starting
- with this one. This Rexx/2 command file searches your entire desktop for a
- folder called "EDM/2" and creates one on the desktop if it cannot find an
- existing one. After doing this, it creates a shadow object within that folder
- that is linked to the filename of the current issue as distributed in the zip
- file (so if you change the name, it will not work). Finally, it sets the icon
- of the file to a newspaper so that you can spot it in a crowd.
-
- INSTALL.CMD makes the following assumptions:
-
- o C: is the drive containing the desktop folder hierarchy
- o The desktop root folder is named "d:\OS!2 2.x Desktop" where "x" is the
- version of the operating system. Note that if you reset your desktop using
- the Ctrl-Alt-F1 key combination, the system does not overwrite your existing
- folder, meaning that the actual desktop folder has another name. To get
- around this, you will have to edit the installation file (search for
- WP_DESKTOP).
-
- Miscellanea
-
- Last month it seems that we forgot to include the CNR2.ZIP file that was
- supposed to accompany the "Programming the Container Control - Part 2" article,
- so we are including it in this issue's zip file. We apologize for the
- inconvenience.
-
- Also, I have been in contact with Gavin Baker, who was the "Introduction to PM"
- columnist and he expressed a desire to continue writing for EDM/2.
- Unfortunately, he was pressed for time and could not complete his column for
- this issue, so we all will be looking forward to that in the next issue.
-
- Finally, as an update, I have also been contacted by David Singer with whom I
- was able to work out the necessary kinks to make EDM/2 available inside of IBM
- on a regular basis. He will be placing the issues on his Gopher servers (one
- for internal use and one that is reachable via the Internet). We are very
- thankful for his "contribution to the cause" and hope that by his offer we can
- expand our audience (and thus the number of potential authors). For more
- information about reaching the Gopher servers, you can contact him at
- singer@almaden.ibm.com.
-
- Enjoy!
- The Editors
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ <hidden> List of Subscription Testers ΓòÉΓòÉΓòÉ
-
- If you are listed below and did not receive the magazine this month via the
- subscription mailer, please send mail to os2man@panix.com.
-
- aaa@atl.hp.com menieuwp@cs.vu.nl
- abaddon@camelot.bradley.edu mgrice@athena.mit.edu
- acmmdj@gsusgi2.gsu.edu mmc@ehabitat.demon.co.uk
- bab%se40@se01.wg2.waii.com morio@ma2s2.mathematik.uni-karlsruhe.de
- bachww@motcid.rtsg.mot.com mstaedt@va-klaus.va.fh-ulm.de
- beaucham@phy.ulaval.ca mullins@magnum.convex.com
- benji@lise.unit.no pft@master10.zfe.siemens.de
- bhenning@wimsey.com pleitner@cs.curtin.edu.au
- bjorn@ludd.luth.se rcs58639@zach.fit.edu
- c878109@id.dth.dk rdm@csn.org
- chandoni@husc.harvard.edu rickw@umr.edu
- coulman@skdad.usask.ca rik@sci.kun.nl
- d2henan@dtek.chalmers.se rm3@stc06.ctd.ornl.gov
- donsmith@vnet.ibm.com robert.mahoney@f347.n109.z1.fidonet.org
- dradhak@unx.ucc.okstate.edu rodrigc@ecf.toronto.edu
- duffy@theory.chem.ubc.ca roe2@midway.uchicago.edu
- evanc@carbon.isis.org rpr@oce.nl
- ghdai@vax1.umkc.edu satish.movva@uic.edu
- gilbert@yalevm.ycc.yale.edu schaefer@calle2.e.open.de
- gogol@diku.dk schrock@cps.msu.edu
- gt7027c@prism.gatech.edu shawnmac@traider.ersys.edmonton.ab.ca
- heederik@fwi.uva.nl slumos@peewee.cs.unlv.edu
- hepner@gourami.nosc.mil soh3@midway.uchicago.edu
- jarlehto@utu.fi spatel@cs.utexas.edu
- jgarzik@pantera.atl.ga.us stephen.drye@synapse.org
- jjs@iedv6.acd.com timur@seas.gwu.edu
- jlauro@umich.edu visser@sci.kun.nl
- jofried@fzi.de wayne@stidol.mtv.gtegsc.com
- johnh@meaddata.com we44478@is1.bfu.vub.ac.be
- kenton+@cmu.edu whitaker@kean.ucs.mun.ca
- kevin@elvis.wicat.com wjw@eb.ele.tue.nl
- kfischer@hurricane.seas.ucla.edu xtifr@netcom.com
-
-
- ΓòÉΓòÉΓòÉ 4. This Issue's Features ΓòÉΓòÉΓòÉ
-
- The following articles constitute this issue's features:
-
- o Development of a New Window Class - Part 2
- o The Help Manager and Online Documentation
- o OS/2 Installable File Systems - Part 2
- o Programming the Container Control - Part 3
- o A Review of C++ Compilers
-
-
- ΓòÉΓòÉΓòÉ 4.1. Development of a New Window Class - Part 2 ΓòÉΓòÉΓòÉ
-
- Written by Larry Salomon, Jr.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.1. Recapitulation and Regurgitation ΓòÉΓòÉΓòÉ
-
- 0 to 60 MPH in 1 Paragraph
-
- Last issue we discussed the functional and design considerations for the
- development of a loose-leaf paper control. Decided was the control that the
- application programmer should be able to exert on our window class through
- messages and the notifications that should be sent for different types of
- actions. Also, it was determined that window words would be needed to store
- instance data for each window of this class.
-
- Is There Anybody Out There?
-
- Aside from defining the interfaces to the users of this control, we can sit in
- our room with the door shut and - assuming someone slips a slice of pizza or
- two under the door every now and then - eventually we will have something
- useable. So where do we begin? Even though entering text is the primary
- function of this class, we have to know where to draw the text, so painting the
- control will be our first component to implement.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.2. Painting ΓòÉΓòÉΓòÉ
-
- Painting is easier to implement if you can break it down into distinct
- sections; since we defined various components of the paper control last issue,
- we can use those as a starting point.
-
- ΓöÇΓö¼ΓöÇΓöÇ Border
- Γö£ΓöÇΓöÇ Top margin
- Γö£Γö¼ΓöÇ Side margin
- ΓöéΓööΓöÇΓöÇΓöÇ Top, middle, and bottom holes
- ΓööΓö¼ΓöÇ Paper body
- ΓööΓöÇΓöÇΓöÇ One or more text lines
-
- Figure 1. Different parts of the paper control
-
- Above all it most be noted that we cannot make any assumptions about the size
- of the control, unless we force the control to follow sizing constraints (we
- will not). Our options, therefore, are to paint the control ignoring the size
- or to use an abstract coordinate system based on the size when painting begins.
- Obviously, the latter is the more desireable so this will be implemented.
-
- The breakdown of the painting as I chose it is as follows:
-
- o Paint the border, if it exists
- o Paint the lines, both horizontal and vertical
- o Paint the holes
- o Paint the title text
- o Paint the body text
-
- Paint the border
-
- Since some developers might not want a border, a paper style was added -
- PPS_BORDER - to allow them to control this. PM defines its window styles (that
- encompass all windows) to be in the upper word of a ULONG, so PPS_BORDER is
- defined to be x'0001'.
-
- hpsPaint=WinBeginPaint(hwndWnd,NULLHANDLE,&rclPaint);
- WinFillRect(hpsPaint,&rclPaint,CLR_WHITE);
-
- WinQueryWindowRect(hwndWnd,&rclWnd);
-
- //----------------------------------------------------------------
- // Paint the border first
- //
- // +------------+
- // +|-----------+|
- // || ||
- // || ||
- // || ||
- // White -----> || || <----- Dark gray
- // || ||
- // |+------------+
- // +------------+
- //----------------------------------------------------------------
- if ((ulStyle & PPS_BORDER)!=0) {
- GpiSetColor(hpsPaint,CLR_WHITE);
-
- ptlPoint.x=rclWnd.xLeft+1;
- ptlPoint.y=rclWnd.yBottom;
- GpiMove(hpsPaint,&ptlPoint);
-
- ptlPoint.x=rclWnd.xRight;
- ptlPoint.y=rclWnd.yTop-1;
- GpiBox(hpsPaint,DRO_OUTLINE,&ptlPoint,0,0);
-
- GpiSetColor(hpsPaint,CLR_DARKGRAY);
-
- ptlPoint.x=rclWnd.xLeft;
- ptlPoint.y=rclWnd.yBottom+1;
- GpiMove(hpsPaint,&ptlPoint);
-
- ptlPoint.x=rclWnd.xRight-1;
- ptlPoint.y=rclWnd.yTop;
- GpiBox(hpsPaint,DRO_OUTLINE,&ptlPoint,0,0);
-
- WinInflateRect(ppidData->habAnchor,&rclWnd,-2,-2);
- } /* endif */
-
- Paint the lines
-
- I don't know why, but it just seemed better sense to paint the vertical line
- first, which was pink, if memory serves me correctly. This is followed by the
- horizontal lines, which were of a cyan tint. Here, we added three new styles -
- holes left (PPS_HOLESLEFT x'0000'), holes right (PPS_HOLESRIGHT x'0002'), and
- no holes (PPS_HOLESNONE x'0004') - which we check when drawing the vertical
- line.
-
- //----------------------------------------------------------------
- // Paint the vertical line. Check the window style to see what
- // side it is on.
- //----------------------------------------------------------------
- if ((ulStyle & PPS_HOLESNONE)!=0) {
- ptlPoint.x=rclWnd.xLeft+ppidData->fmFont.lAveCharWidth*5;
- } else
- if ((ulStyle & PPS_HOLESRIGHT)!=0) {
- ptlPoint.x=rclWnd.xRight-ppidData->fmFont.lAveCharWidth*5;
- } else {
- ptlPoint.x=rclWnd.xLeft+ppidData->fmFont.lAveCharWidth*5;
- } /* endif */
-
- ptlPoint.y=rclWnd.yBottom;
- GpiMove(hpsPaint,&ptlPoint);
-
- ptlPoint.y=rclWnd.yTop;
- GpiSetColor(hpsPaint,CLR_PINK);
- GpiLine(hpsPaint,&ptlPoint);
-
- //----------------------------------------------------------------
- // Paint the horizontal lines. Our strategy is to query each
- // line rectangle, and draw a line along the top edge of this
- // rectangle. This means the bottom edge of the bottom line
- // will not get painted, so explicitly handle this case.
- //----------------------------------------------------------------
- GpiSetColor(hpsPaint,CLR_DARKCYAN);
-
- for (sIndex=0; sIndex<ppidData->sMaxLines; sIndex++) {
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(sIndex));
- ptlPoint.x=rclWnd.xLeft;
- ptlPoint.y=rclLine.yTop;
- GpiMove(hpsPaint,&ptlPoint);
- ptlPoint.x=rclWnd.xRight;
- GpiLine(hpsPaint,&ptlPoint);
- } /* endfor */
-
- ptlPoint.x=rclWnd.xLeft;
- ptlPoint.y=rclLine.yBottom-1;
- GpiMove(hpsPaint,&ptlPoint);
- ptlPoint.x=rclWnd.xRight;
- GpiLine(hpsPaint,&ptlPoint);
-
- Paint the holes
-
- In the future, we might want to support four- and seven- hole paper, so we have
- to query the number of holes. We then loop, drawing each hole, until done.
-
- //----------------------------------------------------------------
- // Note that if PPS_HOLESNONE was specified, 0 is returned
- //----------------------------------------------------------------
- usMaxHoles=SHORT1FROMMR(WinSendMsg(hwndWnd,PPM_QUERYNUMHOLES,0,0));
-
- for (sIndex=0; sIndex<usMaxHoles; sIndex++) {
- WinSendMsg(hwndWnd,
- PPM_QUERYHOLERECT,
- MPFROMP(&rclHole),
- MPFROMSHORT(sIndex));
-
- ptlPoint.x=rclHole.xLeft+(rclHole.xRight-rclHole.xLeft)/2;
- ptlPoint.y=rclHole.yBottom+(rclHole.yTop-rclHole.yBottom)/2;
- GpiMove(hpsPaint,&ptlPoint);
- GpiSetColor(hpsPaint,CLR_PALEGRAY);
- GpiFullArc(hpsPaint,
- DRO_FILL,
- MAKEFIXED(ppidData->fmFont.lAveCharWidth,0));
- GpiSetColor(hpsPaint,CLR_DARKGRAY);
- GpiFullArc(hpsPaint,
- DRO_OUTLINE,
- MAKEFIXED(ppidData->fmFont.lAveCharWidth,0));
- } /* endfor */
-
- Paint the title text
-
- If there is any title text (set on the WinCreateWindow() call or via
- WinSetWindowText()), we draw it here.
-
- if (ppidData->pchTitle!=NULL) {
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(0));
- rclLine.yBottom=rclLine.yTop+1;
- rclLine.yTop=rclLine.yBottom+ppidData->fmFont.lMaxBaselineExt;
-
- WinDrawText(hpsPaint,
- -1,
- ppidData->pchTitle,
- &rclLine,
- ppidData->lForeClr,
- 0,
- DT_CENTER);
- } /* endif */
-
- Paint the body text
-
- Finally, we paint the body text, using the PPM_CONVERTPOINTS message to convert
- the invalid rectangle from world to line coordinates. While this is the only
- optimization of the paint process, we could easily extend this to the other
- components of the control.
-
- WinSendMsg(hwndWnd,
- PPM_CONVERTPOINTS,
- MPFROMP(&rclPaint),
- MPFROMSHORT(2));
-
- if (rclPaint.yTop<0) {
- rclPaint.yTop=0;
- } /* endif */
-
- if ((rclPaint.yBottom>ppidData->sMaxLines-1) ||
- (rclPaint.yBottom<0)) {
- rclPaint.yBottom=ppidData->sMaxLines-1;
- } /* endif */
-
- while (rclPaint.yTop<=rclPaint.yBottom) {
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(rclPaint.yTop));
-
- if (strlen(ppidData->aachLines[rclPaint.yTop])>0) {
- WinDrawText(hpsPaint,
- -1,
- ppidData->aachLines[rclPaint.yTop],
- &rclLine,
- ppidData->lBackClr,
- 0,
- DT_LEFT|DT_BOTTOM);
- } /* endif */
-
- rclPaint.yTop++;
- } /* endwhile */
-
- WinEndPaint(hpsPaint);
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.3. User Input ΓòÉΓòÉΓòÉ
-
- By definition, a window can only receive input when it has the input focus.
- Well, this isn't entirely true, since a window receives mouse movement messages
- regardless of whom has the focus, with the exception of mouse capture, only
- if...All kidding aside, character keystrokes go to the window with the input
- focus and the system notifies a window when it receives and loses the focus, so
- we use this to implement keystroke processing. Our 1000-foot view shows an
- entryfield that belongs to us, created without ES_BORDER, which we position
- over the line in which keystrokes are entered. We let the entryfield handle
- the keyboard interface and we need only to initialize it with any text
- currently on the line, and query it when the line is to change.
-
- First, when can the line number be changed? The answer is ours to define. I
- chose to allow first button clicks to set an absolute line and the up and down
- arrows to change the line by one in either direction.
-
- Second, what happens when the line number changes? Derived from our 1000-foot
- view, we query the entryfield text and update our internal array of line text,
- determine the world coordinates of the new line, call WinSetWindowPos() to
- change the position of the entryfield to reflect this new position, and finally
- initialize the entryfield via WinSetWindowText() with the text of the new line
- as stored in our internal array.
-
- These two questions translate to the messages WM_BUTTON1DOWN and WM_CHAR.
-
- case WM_BUTTON1DOWN:
- {
- RECTL rclWnd;
-
- //----------------------------------------------------------------
- // Before we change the line, update the text array from the
- // current line
- //----------------------------------------------------------------
- if (ppidData->sLine>-1) {
- WinQueryWindowText(ppidData->hwndText,
- sizeof(ppidData->aachLines[ppidData->sLine]),
- ppidData->aachLines[ppidData->sLine]);
- } /* endif */
-
- //----------------------------------------------------------------
- // Query the line clicked on
- //----------------------------------------------------------------
- rclWnd.xLeft=SHORT1FROMMP(mpParm1);
- rclWnd.yBottom=SHORT2FROMMP(mpParm1);
-
- WinSendMsg(hwndWnd,
- PPM_CONVERTPOINTS,
- MPFROMP(&rclWnd.xLeft),
- MPFROMSHORT(1));
-
- //----------------------------------------------------------------
- // If the place clicked on is one of the lines, set the new
- // entryfield position to that line
- //----------------------------------------------------------------
- if (rclWnd.yBottom>-1) {
- WinSendMsg(hwndWnd,PPM_SETCURRENTLINE,MPFROMP(rclWnd.yBottom),0);
- WinShowWindow(ppidData->hwndText,TRUE);
- WinSetWindowText(ppidData->hwndText,
- ppidData->aachLines[ppidData->sLine]);
- } else {
- ppidData->sLine=-1;
- WinShowWindow(ppidData->hwndText,FALSE);
- } /* endif */
-
- WinSetFocus(HWND_DESKTOP,hwndWnd);
- }
- break;
- case WM_CHAR:
- if ((CHARMSG(&ulMsg)->fs & (KC_VIRTUALKEY | KC_KEYUP))==
- KC_VIRTUALKEY) {
- switch (CHARMSG(&ulMsg)->vkey) {
- case VK_UP:
- {
- RECTL rclLine;
-
- //----------------------------------------------------------
- // Remember, we can only go up if there is another line
- // above us
- //----------------------------------------------------------
- if (ppidData->sLine>0) {
- WinQueryWindowText(ppidData->hwndText,
- sizeof(ppidData->aachLines[ppidData->sLine]),
- ppidData->aachLines[ppidData->sLine]);
-
- ppidData->sLine--;
-
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(ppidData->sLine));
- WinSetWindowPos(ppidData->hwndText,
- NULLHANDLE,
- rclLine.xLeft,
- rclLine.yBottom,
- 0,
- 0,
- SWP_MOVE);
- WinSetWindowText(ppidData->hwndText,
- ppidData->aachLines[ppidData->sLine]);
-
- //-------------------------------------------------------
- // We only invalidate the line we left because the
- // entryfield paints itself
- //-------------------------------------------------------
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(ppidData->sLine+1));
- WinInvalidateRect(hwndWnd,&rclLine,TRUE);
- WinUpdateWindow(hwndWnd);
-
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_UP),
- MPFROMSHORT(ppidData->sLine));
- } else
- if (ppidData->sLine==0) {
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_BEGINPAGE),
- MPFROMSHORT(ppidData->sLine));
- } /* endif */
- }
- break;
- //----------------------------------------------------------------
- // We treat newline and enter the same as down arrow
- //----------------------------------------------------------------
- case VK_DOWN:
- case VK_NEWLINE:
- case VK_ENTER:
- {
- RECTL rclLine;
-
- //----------------------------------------------------------
- // Remember, we can only go down if there is another line
- // below us
- //----------------------------------------------------------
- if ((ppidData->sLine>-1) &&
- (ppidData->sLine<ppidData->sMaxLines-1)) {
- WinQueryWindowText(ppidData->hwndText,
- sizeof(ppidData->aachLines[ppidData->sLine]),
- ppidData->aachLines[ppidData->sLine]);
-
- ppidData->sLine++;
-
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(ppidData->sLine));
- WinSetWindowPos(ppidData->hwndText,
- NULLHANDLE,
- rclLine.xLeft,
- rclLine.yBottom,
- 0,
- 0,
- SWP_MOVE);
- WinSetWindowText(ppidData->hwndText,
- ppidData->aachLines[ppidData->sLine]);
-
- //-------------------------------------------------------
- // We only invalidate the line we left because the
- // entryfield paints itself
- //-------------------------------------------------------
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(ppidData->sLine-1));
- WinInvalidateRect(hwndWnd,&rclLine,TRUE);
- WinUpdateWindow(hwndWnd);
-
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_DOWN),
- MPFROMSHORT(ppidData->sLine));
- } else
- if (ppidData->sLine==ppidData->sMaxLines-1) {
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_ENDPAGE),
- MPFROMSHORT(ppidData->sLine));
- } /* endif */
- }
- break;
- default:
- return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- } /* endswitch */
- } else {
- return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- } /* endif */
- break;
-
- Notice the notifications PPN_UP, PPN_DOWN, PPN_BEGINPAGE and PPN_ENDPAGE.
-
- Time Out
-
- You will not notice this now, but if you click on the paper control, the line
- number is supposed to change. Why do we not get a flashing cursor where the
- "invisible" entryfield exists? The answer is in the way the system handles
- focus changing.
-
- When the input focus window changes, a number of messages are sent as a result
- to both the window losing the focus and to the window receiving the focus.
- While this messages are being processed, the system considers no one to have
- the focus, so any attempt to change the focus via WinSetFocus() or
- WinFocusChange() will have no effect because the system will "overwrite" the
- focus change as it completes its processing.
-
- The result of this gibberish is that, if we are clicked on, we want the
- entryfield to receive the focus, but since we need to do some processing, we
- cannot just call WinSetFocus(HWND_DESKTOP,ppidData->hwndText) since we will
- never receive any notification.
-
- The result of that gibberish is that we need to get the focus and then somehow
- pass the focus on to the entryfield. Since we cannot change the focus while
- the system changes the focus, we need a little hocus-pocus to achieve this.
-
- #define PRVM_SETFOCUS (WM_USER)
-
- case WM_SETFOCUS:
- WinPostMsg(hwndWnd,PRVM_SETFOCUS,mpParm1,mpParm2);
- break;
- case PRVM_SETFOCUS:
- if (SHORT1FROMMP(mpParm2)) {
- if (ppidData->sLine>-1) {
- WinShowWindow(ppidData->hwndText,TRUE);
- WinFocusChange(HWND_DESKTOP,
- ppidData->hwndText,
- FC_NOLOSEACTIVE|FC_NOLOSEFOCUS|FC_NOLOSESELECTION);
- } /* endif */
-
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_SETFOCUS),
- 0);
- } else {
- //----------------------------------------------------------------
- // If we're losing the focus, update the text array, but leave the
- // entryfield text alone.
- //----------------------------------------------------------------
- if (ppidData->sLine>-1) {
- WinQueryWindowText(ppidData->hwndText,
- sizeof(ppidData->aachLines[ppidData->sLine]),
- ppidData->aachLines[ppidData->sLine]);
- WinShowWindow(ppidData->hwndText,FALSE);
- } /* endif */
-
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),
- PPN_KILLFOCUS),
- 0);
- } /* endif */
- break;
-
- In the code above, a couple of things need to be noted:
-
- o The hocus-pocus is in the call to WinPostMsg(). While it is not guaranteed,
- it is highly likely that our message will get processed after the system
- finished the focus change. This will allow us to do any processing necessary
- and then change the focus again to the entryfield.
-
- o The focus change added two new notifications - PPN_SETFOCUS and
- PPN_KILLFOCUS. These have the same semantics as the corresponding entryfield
- notifications EN_SETFOCUS and EN_KILLFOCUS.
-
- o The call to WinFocusChange() specifies through the use of the FC_* constants
- that the window with the focus (that's us) should not receive any
- notification that it is losing the focus. This is needed so that we don't
- send the PPN_KILLFOCUS notification.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.4. Owner Notifications ΓòÉΓòÉΓòÉ
-
- Last issue, we defined a list of four events that should result in a
- notification to the owner window. The system allows us to define any
- notification code as a USHORT that we feel is necessary, since there is no
- "standard list" of notifications present for all window classes (versus window
- styles, where there is a common set of styles).
-
- The cursor moves up or down
-
- This is implemented in the processing for WM_CHAR. The code consists of the
- following call to WinSendMsg().
-
- WinSendMsg(ppidData->hwndOwner,
- WM_CONTROL,
- MPFROM2SHORT(WinQueryWindowUShort(hwndWnd,QWS_ID),PPN_UP),
- MPFROMSHORT(ppidData->sLine));
-
- Substitute PPN_DOWN for PPN_UP as needed.
-
- Note that if the cursor is on line 1/ppidData->sMaxLines and the user presses
- the up/down arrow, we instead send a PPN_BEGINPAGE/PPN_ENDPAGE notification to
- let the application know that the page boundary was reached.
-
- Any mouse button is clicked or double-clicked
-
- This is implemented in the processing for the various WM_BUTTONxUP and
- WM_BUTTONxDBLCLK messages. The code is the same as for the PPN_UP/PPN_DOWN
- notifications with the notification code changed as appropriate. Note that we
- could use the second half of mpParm2 to include which button was pressed, as a
- convenience to the user.
-
- The system-defined sequence for displaying the context menu is pressed
-
- Again, we use the same call to WinSendMsg(), this time from the WM_CONTEXTMENU
- message.
-
- Help is requested
-
- And finally one more WinSendMsg() from the WM_HELP message.
-
- That was easy, wasn't it?
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.5. Presentation Parameters ΓòÉΓòÉΓòÉ
-
- Processing these is probably the most interesting, because...well, because the
- ability for the user to change the color and font of a window was new with OS/2
- 2.0. [Get on soapbox] "I remember the days when you didn't have to deal with
- these dad-burned paramitization presentations or whatever the hell they're
- called."[Get off soapbox]. Because the user has the ability, via the color and
- font palettes, to change your presentation parameters, you can no longer avoid
- them when developing a new window class.
-
- Changing a presentation parameter is done for you by the system, providing you
- use a micro-cache'd presentation space in all of your drawing operations
- (obtained through WinBeginPaint() with NULLHANDLE specified as the second
- parameter, or through WinGetPS()). If you have your own screen presentation
- space which you specify in the call to WinBeginPaint, you will need to
- intercept the WM_PRESPARAMCHANGED message. Another time this message is needed
- is if you need the size of the current font for other processing or will
- unconditionally set the color to some color but want to restore it for other
- operations.
-
- Gee, aren't those familiar operations?
-
- We intercept this message and if a color was changed, we query the new color
- value and store that in our instance data. If the font changed, we re-query
- the FONTMETRICS structure values so that we can base our line size on the
- height of the font.
-
- case WM_PRESPARAMCHANGED:
- switch (LONGFROMMP(mpParm1)) {
- case PP_FOREGROUNDCOLOR:
- case PP_FOREGROUNDCOLORINDEX:
- {
- ULONG ulId;
- LONG lColor;
- HPS hpsWnd;
- SHORT sIndex;
- RECTL rclLine;
-
- WinQueryPresParam(hwndWnd,
- PP_FOREGROUNDCOLORINDEX,
- LONGFROMMP(mpParm1),
- &ulId,
- sizeof(lColor),
- &lColor,
- QPF_NOINHERIT);
-
- if (ulId==PP_FOREGROUNDCOLOR) {
- hpsWnd=WinGetPS(hwndWnd);
- lColor=GpiQueryColorIndex(hpsWnd,0,lColor);
- WinReleasePS(hpsWnd);
- } /* endif */
-
- ppidData->lForeClr=lColor;
-
- for (sIndex=0; sIndex<ppidData->sMaxLines; sIndex++) {
- if (ppidData->aachLines[sIndex][0]!=0) {
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(sIndex));
- WinInvalidateRect(hwndWnd,NULL,TRUE);
- } /* endif */
- } /* endfor */
-
- WinUpdateWindow(hwndWnd);
- }
- break;
- case PP_BACKGROUNDCOLOR:
- case PP_BACKGROUNDCOLORINDEX:
- {
- ULONG ulId;
- LONG lColor;
- HPS hpsWnd;
- SHORT sIndex;
- RECTL rclLine;
-
- WinQueryPresParam(hwndWnd,
- PP_BACKGROUNDCOLORINDEX,
- LONGFROMMP(mpParm1),
- &ulId,
- sizeof(lColor),
- &lColor,
- QPF_NOINHERIT);
-
- if (ulId==PP_BACKGROUNDCOLOR) {
- hpsWnd=WinGetPS(hwndWnd);
- lColor=GpiQueryColorIndex(hpsWnd,0,lColor);
- WinReleasePS(hpsWnd);
- } /* endif */
-
- ppidData->lBackClr=lColor;
-
- for (sIndex=0; sIndex<ppidData->sMaxLines; sIndex++) {
- if (ppidData->aachLines[sIndex][0]!=0) {
- WinSendMsg(hwndWnd,
- PPM_QUERYLINERECT,
- MPFROMP(&rclLine),
- MPFROMSHORT(sIndex));
- WinInvalidateRect(hwndWnd,NULL,TRUE);
- } /* endif */
- } /* endfor */
-
- WinUpdateWindow(hwndWnd);
- }
- break;
- case PP_FONTNAMESIZE:
- case PP_FONTHANDLE:
- {
- HPS hpsWnd;
- RECTL rclWnd;
-
- hpsWnd=WinGetPS(hwndWnd);
- GpiQueryFontMetrics(hpsWnd,sizeof(FONTMETRICS),&ppidData->fmFont);
- WinReleasePS(hpsWnd);
-
- WinQueryWindowRect(hwndWnd,&rclWnd);
- WinSendMsg(hwndWnd,
- WM_SIZE,
- 0,
- MPFROM2SHORT((SHORT)rclWnd.xRight,
- (SHORT)rclWnd.yTop));
- WinInvalidateRect(hwndWnd,NULL,TRUE);
- WinUpdateWindow(hwndWnd);
- }
- break;
- default:
- return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- } /* endswitch */
- break;
-
- Again, there are other (better) ways of implementing things. Here, we could
- query the RGB value of the changed color and use that in our painting to get
- the most accuracy. This exercise is left up to the programmer.
-
- While it doesn't really belong here, the window text processing has nowhere
- else to go so it is discussed here. The system's interface to a window class
- for items like this is through the WM_SETWINDOWPARAMS and WM_QUERYWINDOWPARAMS
- messages. The former is sent when a window parameter changes and the latter is
- sent to query the data from the window. A window parameter is either the
- window text or the control data (which is specific to a window class) and both
- are bundled in the WNDPARAMS structure.
-
- typedef struct _WNDPARAMS {
- ULONG fsStatus;
- ULONG cchText;
- PSZ pszText;
- ULONG cbPresParams;
- PVOID pPresParams;
- ULONG cbCtlData;
- PVOID pCtlData;
- } WNDPARAMS, *PWNDPARAMS;
-
- fsStatus For queries by the system, this specifies (as a combination
- of WPM_* constants) the parameters to query.
- cchText This specifies the size of the data pointed to by pszText
- pszText This points to the window text, terminated by a NULL
- character
- cbPresParams This specifies the size of the data pointed to by
- pPresParams
- pPresParams This points to the presentation parameters
- cbCtlData This specifies the size of the data pointed to by pCtlData
- pCtlData This points to the control data
-
- Since we are interested in the text only, we check the fsStatus field for the
- WPM_TEXT constant explicitly and act accordingly. The resulting code is shown
- below:
-
- case WM_QUERYWINDOWPARAMS:
- {
- PWNDPARAMS pwpParms;
-
- pwpParms=(PWNDPARAMS)PVOIDFROMMP(mpParm1);
-
- if ((pwpParms->fsStatus & WPM_TEXT)!=0) {
- pwpParms->pszText[0]=0;
- strncat(pwpParms->pszText,ppidData->pchTitle,pwpParms->cchText);
- WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- return MRFROMSHORT(TRUE);
- } /* endif */
-
- return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- }
- case WM_SETWINDOWPARAMS:
- {
- BOOL bProcessed;
- PWNDPARAMS pwpParms;
-
- bProcessed=FALSE;
- pwpParms=(PWNDPARAMS)PVOIDFROMMP(mpParm1);
-
- if ((pwpParms->fsStatus & WPM_TEXT)!=0) {
- if (ppidData->pchTitle!=NULL) {
- free(ppidData->pchTitle);
- ppidData->pchTitle=NULL;
- } /* endif */
-
- if ((pwpParms->pszText!=NULL) && (strlen(pwpParms->pszText)>0)) {
- ppidData->pchTitle=malloc(strlen(pwpParms->pszText)+1);
- strcpy(ppidData->pchTitle,pwpParms->pszText);
- } /* endif */
-
- bProcessed=TRUE;
- } /* endif */
-
- if (bProcessed) {
- WinInvalidateRect(hwndWnd,NULL,TRUE);
- WinUpdateWindow(hwndWnd);
- WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- return MRFROMSHORT(TRUE);
- } else {
- return WinDefWindowProc(hwndWnd,ulMsg,mpParm1,mpParm2);
- } /* endif */
- }
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.1.6. Summary ΓòÉΓòÉΓòÉ
-
- Although a lot of code was presented here, all of it is really only the
- extension of our thoughts from last issue when this new class was being
- designed. It cannot be stressed enough the importance of a good design; no one
- expects you to get it right the first time, but if you think most of it through
- the rest becomes significantly easier.
-
- As a final note, all coordinates that we discussed here were (if not already)
- mapped to line numbers via the message PPM_CONVERTPOINTS. This allows us to
- change the size of each line in one place only. This logic was applied in
- other places (PPM_QUERYNUMHOLES) to make our maintenance easier and goes way
- back to Computer Science 101 when code modularity was discussed.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2. The Help Manager and Online Documentation ΓòÉΓòÉΓòÉ
-
- Written by Larry Salomon, Jr.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.1. Introduction ΓòÉΓòÉΓòÉ
-
- More times than I care to remember, I have been asked "How do I add online help
- to my applications?" or "How can I write online books?" While the latter takes
- less time to answer, I often myself talking for 45 minutes or so on everything
- from what an GML language is to the sequence of events that happen when a user
- presses the F1 key.
-
- Finally, today I got tired of repeating myself (even as much as I love to talk)
- so I decided to write the article that has been promised for so long. Hopefully
- after reading this, you should be able to do the following:
-
- o Briefly explain what an GML language is and what markup is
-
- o List the three components needed when adding context-sensitive help to a PM
- application and what each component's purpose is
-
- o Describe the sequence of events that occur when a user presses F1
-
- o Detail the minimum markup required to create a valid online help file and to
- create a valid online book file
-
- o Be able to write the markup for headings, paragraphs, lists (all five types),
- emphasis, hypertext links, and graphics.
-
- o Explain some of the limitations of the IPFC compiler
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.2. The Basics ΓòÉΓòÉΓòÉ
-
- GML is an acronym for generalized markup language and describes a group of
- languages which perform operations on blocks of text. Typically, these
- languages are used for output formatting but are not limited to this arena.
- The language consists of control words (called tags) interspersed within blocks
- of text; these tags have the form
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :tag [attribute[=value] [attribute[=value] [...]]].[text]
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 1. GML tag syntax
-
- The attributes shown above vary from tag to tag and may not exist at all.
- Likewise, each attribute may or may not accept a value; consult the
- "Information Presentation Facility" reference guide which comes with the 2.x
- toolkit for a complete list of the attributes for each tag.
-
- Frequently, a tag is used to mark the beginning of a change in formatting and
- has a corresponding end tag to signify the end of that change. The end tag
- often is the same as the begin tag prefixed with an "e". Thus, you use :hp2.
- to begin emphasis level 2 and :ehp2. to end it.
-
- The term markup is used to describe a combination of tags and text in a GML
- file.
-
- Application components
-
- There are three help-related components to any PM application, listed below.
-
- o Source code - calls to and from the Help Manager from your application
-
- o Resources - relationships between focus windows and help panels
-
- o Panel definitions - GML source describing the help panels' appearance
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.3. Source code ΓòÉΓòÉΓòÉ
-
- This consists of the various calls to Help Manager functions from within your
- PM application. The bare minimum exists in your main() function and creates an
- instance of the Help Manager:
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- #define INCL_WINHELP
- :
-
- INT main(USHORT usArgs,PCHAR apchArgs[])
- {
- :
- HELPINIT hiHelp;
-
- habAnchor=WinInitialize(0);
- hmqQueue=WinCreateMsgQueue(habAnchor,0);
- :
- : /* Create frame window */
- :
- if (hwndFrame!=NULLHANDLE) {
- :
- : /* Initialize HELPINIT structure */
- :
- hwndHelp=WinCreateHelpInstance(habAnchor,&hiHelp);
- WinAssociateHelpInstance(hwndHelp,hwndFrame);
- :
- : /* Message loop in here somewhere */
- :
- WinDestroyHelpInstance(hwndHelp);
- WinDestroyWindow(hwndFrame);
- } /* endif */
-
- WinDestroyMsgQueue(hmqQueue);
- WinTerminate(habAnchor);
- }
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 2. Help Manager initialization
-
- The HELPINIT structure is a rather large conglomeration of configurable items.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- typedef struct _HELPINIT {
- ULONG cb;
- ULONG ulReturnCode;
- PSZ pszTutorialName;
- PHELPTABLE phtHelpTable;
- HMODULE hmodHelpTableModule;
- HMODULE hmodAccelActionBarModule;
- ULONG idAccelTable;
- ULONG idActionBar;
- PSZ pszHelpWindowTitle;
- ULONG fShowPanelId;
- PSZ pszHelpLibraryName;
- } HELPINIT, *PHELPINIT;
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 3. HELPINIT structure
-
- cb Specifies the size of the structure in bytes
-
- ulReturnCode On exit, contains any error codes returned from the Help
- Manager
-
- pszTutorialName Points to the string specifying the default tutorial name.
- If NULL, there is no default tutorial or it is specified in
- the panel definition file.
-
- phtHelpTable Points to the HELPTABLE to use, or specifies the resource
- id of the HELPTABLE to be loaded from the resource file.
- If this specifies the resource id, it is contained in the
- low word and the high word must be 0xFFFF.
-
- hmodHelpTableModule Specifies the handle of the module from whence the
- HELPTABLE is to be loaded.
-
- idAccelTable Specifies the resource id of the accelerator table to be
- used. A value of 0 specifies that the default is to be
- used.
-
- idActionBar Specifies the resource id of the action bar to be used. A
- value of 0 specifies that the default is to be used.
-
- hmodAccelActionBarModule Specifies the handle of the module from whence the
- accelerator table and action bar are to be loaded.
-
- pszHelpWindowTitle Points to the help window title text.
-
- fShowPanelId Specifies whether or not to show the panel identifier (if
- present). Valid values are CMIC_SHOW_PANEL_ID and
- CMIC_HIDE_PANEL_ID.
-
- pszHelpLibraryName Points to the filename containing the compiler panel
- definitions.
-
- It needs to be noted that even though a valid window handle is returned from
- WinCreateHelpInstance(), an error might have occurred whose value is specified
- in the ulReturnCode field of the HELPINIT structure.
-
- Messages
-
- There will be times when you will want to send messages to the Help Manager and
- when messages will be received. The four most frequent messages sent to the
- Help Manager are listed below:
-
- HM_HELP_INDEX Causes the help index to be displayed
- HM_EXT_HELP Causes the extended (general) help panel defined for the
- active window to be displayed (described more later)
- HM_DISPLAY_HELP Causes the panel specified by name (in mpParm1) or resource
- id (in mpParm2) to be displayed. Specifying NULL and 0 for
- these values cause the "Using Help" panel to be displayed.
- HM_KEYS_HELP Causes the keys help panel to be displayed. Since the
- active key set is dependent on the current state of the
- application, this cannot be statically defined in the
- resource tables. Instead, the Help Manager responds by
- sending your application an HM_QUERY_KEYS_HELP message to
- get the resource id of the keys help panel.
-
- The following three messages sent to your application are probably the most
- widely used:
-
- HM_ERROR Sent whenever an error occurs between the time F1 is
- pressed and the help operation ends. The error code is
- specified in mpParm1
- HM_HELPSUBITEM_UNDEFINED Sent whenever help was requested but no entry in the
- HELPSUBTABLE was found.
- HM_INFORM Sent whenever a link with the inform attribute is
- encountered.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.4. Resources ΓòÉΓòÉΓòÉ
-
- To make the connection between a window and a help panel, two new resource
- types were added to PM's resource file definition - HELPTABLEs and
- HELPSUBTABLEs. Together, they specify an array of variable length lists that
- map a window resource id to a help panel resource id.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- HELPTABLE RES_CLIENT
- {
- HELPITEM RES_CLIENT, SUBHELP_CLIENT, GENHELP_CLIENT
- HELPITEM RES_DIALOG1, SUBHELP_DIALOG1, GENHELP_DIALOG1
- HELPITEM RES_DIALOG2, SUBHELP_DIALOG2, GENHELP_DIALOG2
- :
- HELPITEM RES_DIALOGn, SUBHELP_DIALOGn, GENHELP_DIALOGn
- }
-
- HELPSUBTABLE SUBHELP_CLIENT
- {
- HELPSUBITEM WID_WINDOW1, HID_PANEL1
- HELPSUBITEM WID_WINDOW2, HID_PANEL2
- :
- HELPSUBITEM WID_WINDOWn, HID_PANELn
- }
-
- HELPSUBTABLE SUBHELP_DIALOG1
- {
- HELPSUBITEM WID_WINDOW1, HID_PANEL1
- HELPSUBITEM WID_WINDOW2, HID_PANEL2
- :
- HELPSUBITEM WID_WINDOWn, HID_PANELn
- }
-
- HELPSUBTABLE SUBHELP_DIALOG2
- {
- HELPSUBITEM WID_WINDOW1, HID_PANEL1
- HELPSUBITEM WID_WINDOW2, HID_PANEL2
- :
- HELPSUBITEM WID_WINDOWn, HID_PANELn
- }
-
- HELPSUBTABLE SUBHELP_DIALOG3
- {
- HELPSUBITEM WID_WINDOW1, HID_PANEL1
- HELPSUBITEM WID_WINDOW2, HID_PANEL2
- :
- HELPSUBITEM WID_WINDOWn, HID_PANELn
- }
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 4. Help Manager resource structures
-
- Each HELPITEM specifies the resource id of an active window, the id of the
- HELPSUBTABLE associated with this window, and the resource id of the General
- Help panel associated with this window.
-
- Each HELPSUBITEM specifies a focus window resource id (WID_*) and a
- corresponding help panel resource id (HID_*).
-
- What are the rules that the Help Manager uses to get from F1 to a help panel
- id? To answer that question, we need to know the sequence of events that occur
- when a user presses F1. Below, we assume that the application is help-enabled.
-
- 1. The user presses F1
-
- 2. The Help Manager queries the active window resource id (ID1) and the focus
- window id (ID2).
-
- 3. ID1 is used in a lookup of the HELPTABLE to determine the HELPSUBTABLE to
- use.
-
- 4. ID2 is used in a lookup of the HELPSUBTABLE to find the resource id of the
- help panel to display.
-
- 5. The Help Manager displays the panel.
-
- There are two obvious error conditions: 1) there is no HELPSUBTABLE for the
- active window and 2) there is no HELPSUBITEM for the focus window. The former
- is resolved by examining each window in the parent window chain until a window
- that does have a HELPSUBTABLE is found and then the process continues as
- normal. If this still yields nothing, the owner window chain is searched and
- then if nothing still, an error message is sent to the active window. The
- latter is resolved by first sending an HM_HELPSUBITEM_UNDEFINED message to
- attempt to alleviate the situation. If the application returns FALSE the
- general help panel specified on the HELPITEM statement is displayed.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.5. Panel definitions ΓòÉΓòÉΓòÉ
-
- This is, by far, the most time-consuming portion of help-enabling. Not only do
- you have to write the text to be displayed, but you must also be aware of
- formatting options and what effect they have on the output. At a minimum, you
- must have the following to create a valid online help file:
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :userdoc.
- :h1.Heading 1
- :p.Paragraph 1
- :euserdoc.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 5. Minimum GML markup
-
- The tags used above are described below:
-
- :userdoc. Specifies the beginning of a user document.
-
- :h1. Specifies a heading level 1.
-
- :p. Specifies a new paragraph.
-
- :euserdoc. Specifies the end of the user document.
-
- Online book writers must also specify a :title.Document title after the
- :userdoc. tag.
-
- As you can imagine, this file doesn't do much. In fact, it does nothing since
- as you can see nowhere are an help panel resource ids specified (even though
- you don't know how to specify them). For that matter, what defines a panel?
-
- A panel is a block of formatted text beginning with a heading level and ending
- with the beginning of the next panel displayed in the table of contents or the
- end of the document body. (the back matter of a document can contain an
- index.) Heading levels are specifies after the h and can be in the range 1-9;
- by default, only heading levels 1-3 are displayed in the table of contents, but
- this is configurable using the :docprof. tag. A heading may also have
- attributes; these are the res, id, name, and hide attributes.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :hn [res=value][id=value][name=value][hide].
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 6. Heading tag syntax
-
- res=value This specifies a numeric resource id for the panel and is
- used in the HELPSUBITEM definitions and can be used to
- specify the target of a hypertext link.
- id=value This specifies an alphanumeric id that can be used to
- specify the target of a hypertext link.
- name=value This specifies an alphanumeric id that can be referenced by
- an application.
- hide This specifies that, regardless of the heading level, the
- panel should not show up in the table of contents. This is
- useful for hypertext links.
-
- Headings must have data associated with them, i.e. you cannot have an :h1. tag
- immediately followed by an :h2. tag. Also, heading levels other than 1 that
- are ordinally higher than their predecessors must have the next cardinal value.
- Thus, the first example is valid while the second is not:
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :h1.Heading 1
- :p.Blah blah blah
- :h2.Heading 2
- :p.Blah blah blah
- :h1.Heading 1
- :p.Blah blah blah
-
- :h1.Heading 1
- :p.Blah blah blah
- :h3.Heading 3
- :p.Blah blah blah
- :h1.Heading 1
- :p.Blah blah blah
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 7. Heading examples
-
- This does not apply to headings that have a lower value than their
- predecessors.
-
- Paragraphs
-
- The most frequently used tag is probably the :p. tag, used to begin a new
- paragraph. It should be noted that some constructs implictly begin on a new
- paragraph, so this is not needed. A paragraph is denoted by ending the current
- line, inserting a blank line, and continuing on the next line. The current
- indentation level (modified by lists, etc.) is not changed.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :p.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 8. Paragraph tag syntax
-
- A word here should be mentioned about symbols. What happens when you want to
- put a colon (:) in your panels? How is the compiler going to be able to
- differentiate between a colon as part of the text or as the beginning of a tag.
- GML defines a syntax for symbols such that they begin with an ampersand (&) and
- end with a period with a symbol name in the middle. Thus, a colon is &colon.,
- and ampersand is &., etc.. Some other commonly used symbols appear below:
-
- &lbrk. Left bracket ([)
- &rbrk. Right bracket (])
- &lbrc. Left brace ({)
- &rbrc. Right brace (})
- &vbar. Vertical bar (|)
- &apos. Apostrophe (')
- &bsl. Backslash (\)
- &odq. Open double quote (")
- &cdq. Close double quote (")
- &osq. Open single quote (`)
- &csq. Close single quote (')
-
- You should use the symbol syntax instead of the actual characters whenever
- possible to ease the process of translating your IPF source to other languages,
- should that happen, since the compiler defines the code point to which each
- symbol is mapped according to the codepage in effect.
-
- Lists
-
- IPF (Information Presentation Facility - the language definition) defines five
- types of lists - simple, unordered, ordered, definition, and parameter. All
- lists consist of a begin tag, one or more list items, and an end tag.
- Definition and parameter list items are unique in that they consist of two
- parts.
-
- The begin tags/end tags are :sl./:esl., :ul./:eul., :ol./:eol., :dl./:edl., and
- :parml./:eparml. for simple, unordered, ordered, definition, and parameter
- lists respectively. List items for the first three types are specified using
- the :li. tag. Definition list terms are specified using the :dt. tag, and the
- corresponding definitions using the :dd. tag. Parameter list items are
- specifies using the :pt. tag and - like the definition lists - each item has a
- corresponding definition specified using the :pd. tag.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :sl [compact].
- :li.text
- :esl.
-
- :ul [compact].
- :li.text
- :eul.
-
- :ol [compact].
- :li.text
- :eol.
-
- :dl [tsize=value][compact][break={ all | none | fit }].
- [:dthd.text]
- [:ddhd.text]
- :dt.text
- :dd.text
- :edl.
-
- :parml [tsize=value][compact][break={ all | none | fit }].
- :pt.text
- :pd.text
- :eparml.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 9. List tags syntax
-
- Below are some examples of lists.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :sl.
- :li.Simple list item 1
- :li.Simple list item 2
- :li.Simple list item 3
- :esl.
-
- :ul.
- :li.Unordered list item 1
- :li.Unordered list item 2
- :li.Unordered list item 3
- :eul.
-
- :ol.
- :li.Ordered list item 1
- :li.Ordered list item 2
- :li.Ordered list item 3
- :eol.
-
- :dl.
- :dt.Term 1
- :dd.Definition 1
- :dt.Term 2
- :dd.Definition 2
- :dt.Term 3
- :dd.Definition 3
- :edl.
-
- :parml.
- :pt.Parameter 1
- :pd.Definition 1
- :pt.Parameter 2
- :pd.Definition 2
- :pt.Parameter 3
- :pd.Definition 3
- :eparml.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 10. Examples of list markup
-
- The above are formatted as:
-
- Simple list item 1
-
- Simple list item 2
-
- Simple list item 3
-
- o Unordered list item 1
-
- o Unordered list item 2
-
- o Unordered list item 3
-
- 1. Ordered list item 1
-
- 2. Ordered list item 2
-
- 3. Ordered list item 3
-
- Term 1 Definition 1
-
- Term 2 Definition 2
-
- Term 3 Definition 3
-
- Parameter 1
- Definition 1
-
- Parameter 2
- Definition 2
-
- Parameter 3
- Definition 3
-
- All lists accept the attribute compact which specifies that items should not be
- separated by blank lines. Definition and parameter lists also accept the
- attributes tsize=value and break=[all | fit | none]. tsize specifies the width
- of the term column in units of the average character width of the current font.
- break specifies what is to be done when the term exceeds the column width; the
- default is none and starts the definition after the term preceeded by a space.
- all specifies that all definitions begin on a new line indented by the term
- column width. fit specifies that definitions whose terms exceed the column
- width begin on a new line as in all.
-
- Emphasis
-
- Emphasis markups consist of a begin and end tag and have the form :hpn. There
- are different emphasis levels, ranging from 1 to 9, which is specified as n.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :hpn.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 11. Emphases tag syntax
-
- Level Meaning
- 1 Italic
- 2 Bold
- 3 Italicized bold
- 4 Alternate color 1
- 5 Underlined
- 6 Underlined italic
- 7 Underlined bold
- 8 Alternate color 2
- 9 Alternate color 3
-
- Emphasis markup has no attributes.
-
- Hypertext
-
- Ever since online documentation became all-the-rage, one of the greatest
- advantages that it touted was the elimination of the phrase "For more
- information, see page...". Hypertext - as it was termed - is the ability to
- jump from one point to another by performing some action (usually a click of
- the mouse) on a hot-link; these hot-links are usually a word or phrase that has
- more, related information associated with it that the user will supposedly want
- to read eventually but without cluttering up the topic already being read.
-
- Hypertext in IPF markup is accomplished using the :link. tag and its
- corresponding end tag.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :link reftype={ fn | hd | launch | inform } [res=value][refid=value]
- [object='value'][data='value'][x=value y=value cx=value cy=value].
- :elink.
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 12. Hypertext tag syntax
-
- The type of the link destination is specified by the reftype parameter. It can
- have one of the following values:
-
- fn Footnote. The footnote must have an id attribute which is
- specified in the refid parameter.
- hd Panel. The panel must have either an id or a resource id
- specified using the id and res attributes, respectively.
- This identifier is specifies in the refid and res
- attributes of the link tag.
- launch Application. The application, whose full path, name, and
- extension must be specified in the object attribute is
- executed. Any command line parameters may be specified in
- the data attribute.
- inform Message. This is applicable to online help only. The
- active window is sent an HM_INFORM message with the value
- of the res attribute passed in mpParm1.
-
- Hypertext links can be used to allow access to panels displayed elsewhere or
- not displayed at all; for example, suppose that you are on heading level 3 and
- you have some indirectly related information that you want to avoid cluttering
- the panel with. You cannot make it a heading level 4 because it won't show up
- in the table of contents. Linking makes a lot of sense here; make the target
- panel heading hidden and level 1 (to avoid nonsensical error messages from the
- compiler) and then link it to allow the user to read the information only if
- desired.
-
- Graphics
-
- Graphics can be included in your documents also; both OS/2 bitmaps and
- metafiles are supported. I have found it useful to use a screen capture
- program to export a bitmap of my application to a file, annotate it with a
- graphical editor, and then include it in the online help to label the items of
- interest. The tag that is used is the :artwork.. tag.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- :artwork name='filename' [runin][linkfile='filename']
- [align={ left | center | right }]
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 12. Hypertext tag syntax
-
- name specifies the filename containing the bitmap or metafile. runin specifies
- that the graphic does not force an newline before and after the graphic. align
- specifies the justification of the graphic. linkfile is for graphical linking
- (called hypergraphics) and will not be discussed.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.6. The Extra Mile ΓòÉΓòÉΓòÉ
-
- Okay, so you've completely enabled your application to use online help...or
- have you? Actually, with the exception of rare applications, there is one more
- area that needs to be covered and that is message box help.
-
- Message boxes are modal dialogs that contain information for the user - error
- messages, usually. However, there is only so much that you can say in a
- message box; so, there is a style that you can specify on the call to
- WinMessageBox() that says to add a Help pushbutton. Fine, so you have a Help
- pushbutton. The user selects it. Nothing happens. What goes on under the
- covers?
-
- Hooks
-
- What goes on is that the message box receives the WM_HELP message and, because
- it can't determine the window that called WinMessageBox() (for more information
- on why this is so, read the documentation for WinLoadDlg() and pay attention to
- the part about determining the real owner of a dialog), it sends the message to
- the help hook.
-
- What is a help hook? Well, a hook in general is a function that gets called by
- an application (or, in this case, the system) when specific types of events
- occur; thus, a help hook is a function that receives notification of
- help-related events.
-
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- BOOL EXPENTRY helpHook(HAB habAnchor,
- SHORT sMode,
- SHORT sTopic,
- SHORT sSubTopic,
- PRECTL prclPosition);
- ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ
- Figure 13. Help hook function prototype
-
- habAnchor Specifies the anchor block of the thread to receive the
- message
-
- sMode Specifies the context of the help request. The values and
- the contexts are:
-
- HLPM_FRAME When the parent of the focus window is an FID_CLIENT
- window. sTopic is the frame window id, sSubTopic is the
- focus window id, and prclPosition points to the screen
- coordinates of the focus window.
-
- HLPM_WINDOW When the parent of the focus window is not an FID_CLIENT
- window. sTopic is the focus window's parent id,
- sSubTopic and prclPosition have the same meaning as
- HLPM_FRAME.
-
- HLPM_MENU When the application is in menu mode. sTopic contains
- the active action bar item id, sSubTopic contains the id
- of the menu item with the cursor, or -1 if the action
- bar has the cursor.
-
- In message boxes, the Help pushbutton is not defined with the BS_NOPOINTERFOCUS
- style, so it has the focus after it is selected. According to the rules, the
- help hook should get HLPM_WINDOW for the mode and the various identifiers in
- the other parameters. However, this is not the case; the help hook does indeed
- receive HLPM_WINDOW as the mode, but the sTopic parameter is the number
- specified as the fifth parameter to WinMessageBox() (the help button
- identifier). sSubTopic always contains the value 1. I have not verified if
- prclPosition points to the screen coordinates of the focus window.
-
- Before we can utilitize this information, we need to install the help hook
- using the WinSetHook() function. (Don't forget to uninstall it before the
- application exits using the WinReleaseHook() function.) Since the Help Manager
- works by installing its own help hook, and since WinSetHook() puts the hook at
- the beginning of the hook chain, you need to remember two things: 1) install
- your hook after calling WinCreateHelpInstance(), and 2) always return FALSE to
- insure that the next hook in the chain is called.
-
- As an ending note, someone sent me a while back, detailed instructions on a
- short cut which - if I remember correctly - eliminated the need for help hooks
- to provide message box help. Unfortunately, I lost these notes.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.7. Epilogue ΓòÉΓòÉΓòÉ
-
- Now that we have all of the necessary information, we can start developing our
- online help and documents. To compile your IPF source, the Developer's Toolkit
- contains the IPFC compiler. It takes an IPF source file as input and compiles
- it to a HLP binary file in the same directory. For online documents, you need
- to specify the /INF switch which instead produces an INF binary file in the
- same directory.
-
- You will probably notice some limitations with the compiler.
-
- o There is no symbolic substition a la the C preprocessor
-
- o Numbers can only be expressed in decimal
-
- o All artwork must be in the same directory as the source
-
- The first one got so frustrating that I wrote my own IPFC preprocessor which
- processes C-style include files and allows you to substitute the #define macros
- in your IPF source as though it were a symbol. This preprocessor is included,
- as well as the accompanying User's Guide (in INF format, of course). The
- latter two problems could also be resolved by adding functionality to the
- preprocessor, but those features were never implemented.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.2.8. Summary ΓòÉΓòÉΓòÉ
-
- Whew! A lot of information was presented here. Hopefully, you should be able
- to reread the objectives of this article and know the answers to the implied
- questions therein. The importance of online help cannot be understressed
- because as computer systems and applications become more complex, the more
- difficult it becomes to remember every feature that is provided. Online
- documentation is also important in that it provides a good vehicle for
- information dissemination and saves trees.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3. OS/2 Installable File Systems - Part 2 ΓòÉΓòÉΓòÉ
-
- Written by Andre Asselin
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.1. Introduction ΓòÉΓòÉΓòÉ
-
- Last time I went over some of the background information needed to write an
- IFS. In this article, I'll continue on and examine a framework to write a
- split ring 0/ring 3 IFS. This month I'm going to limit myself to just the code
- that does initialization and communication between ring 0 and ring 3; it's
- complicated enough to warrant a full article of it own. The things we will
- cover are:
-
- o How an IFS initializes
- o How to communicate between ring 0 and ring 3
- o How a request to the IFS gets handed up to the control program
-
- This article is going to assume that you're familiar with the concepts of
- programming at ring 0. If this seems a little scary, take heart - the next
- article will finally get down to implementing the actual FS_* calls, and will
- concentrate mostly on ring 3 code.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.2. Project Layout ΓòÉΓòÉΓòÉ
-
- The source code for the project is divided up into two directories, RING0 and
- RING3 (included as IFSR0.ZIP and IFSR3.ZIP - Editor); RING0 holds the ring 0
- source, and RING3 hold the ring 3 source. As I mentioned last time, all IFS's
- must be 16-bit code, so for the source in the RING0 directory, I'm using
- Borland C++ 3.1. The ring 3 side is 32-bit code, however, so for it I'm using
- Borland C++ for OS/2. I haven't tried this code on any other compilers, but it
- should be easily portable. One thing to note is that I'm compiling the code in
- C++ mode and using the C++ extensions for one line comments and anonymous
- unions (see for example R0R3SHAR.H). I also use one Borland #pragma for
- forcing enumerations to be 16 bits. With a few modifications, this source
- should work with any ANSI C compiler.
-
- The contents of the RING0 directory are:
-
- C0.ASM Stripped down Borland C++ startup code
- FSD.H FS_* call prototypes and data structures
- FSH.H FSH_* call prototypes and data structures
- FSHELPER.LIB Import library for file system helpers
- OS216.H Header file for 16-bit OS/2 Dos APIs
- R0.CFG Borland C++ configuration file
- R0.DEF Definition file for the linker
- R0.MAK Make file for the IFS
- R0COMM.C Routines to communicate with the control program
- R0DEVHLP.ASM DevHlp interface routines
- R0DEVHLP.H Header file for DevHlp interface routines
- R0GLOBAL.C Global variable definitions
- R0GLOBAL.H Global variable declarations
- R0INC.H Main include file
- R0R3SHAR.H Shared data structures between the IFS and control program
- R0STRUCT.H IFS private structures
- R0STUBS.C FS_* stub routines
-
- The contents of the RING3 directory are:
-
- FSATT.C Sample attach program
- FSD.H FS_ call prototypes and data structures
- R0R3SHAR.H Shared data structures between the IFS and control program
- R3.CFG Borland C++ configuration file
- R3.MAK Make file for the control program
- R3COMM.C Routines to communicate with the IFS
- R3GLOBAL.H Global variable declarations
- R3INC.H Main include file
- R3STUBS.C FS_* stub routines
-
- The two directories are laid out pretty similarly. Some notes on the files:
-
- o The Rx.MAK file is the make file for the directory, and also generates the
- Rx.CFG file, which contains all the compiler switches for the compiler.
-
- o RxGLOBAL.H contains declarations for all of the global variables used. The
- IFS side also has R0GLOBAL.C which defines all of the global variables. The
- control program side doesn't have a corresponding R3GLOBAL.C because it only
- has one global variable that I thought was better put in R3STUBS.C.
-
- o FSD.H and FSH.H are slightly modified versions of the files by the same name
- distributed with the IFS documentation. They are modified slightly to
- accommodate C++ and some clashes in naming conventions.
-
- o R0R3SHAR.H contains definitions for the data structures that the IFS and
- control program share between themselves. This file is a bit tricky to write
- because you have to get the same results no matter if you compile with a
- 16-bit or 32-bit compiler. This means for example, that you have to
- explicitly declare all your int's long or short so that both compilers do the
- same thing.
-
- o In order to call the DevHlp's from C, we need to write interface functions
- for them. Files RING0\R0DEVHLP.H and RING0\R0DEVHLP.ASM contain the
- prototypes and assembler functions for the DevHlp's that are used in the
- code. The functions use the same parameter ordering as the ones in Steve
- Mastrianni's book "Writing OS/2 2.0 Device Drivers in C", although some of
- the typedefs and semantics are a bit different. I'd like to thank him for
- graciously allowing me to use the same parameter layouts.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.3. Communicating Between Ring 0 and Ring 3 ΓòÉΓòÉΓòÉ
-
- The easiest and fastest way for ring 0 and ring 3 code to communicate is
- through shared memory. The way I implemented it is to have the control program
- allocate two buffers when it initializes: one buffer is used to hold all the
- parameters for a given operation, and the other serves as a data buffer to hold
- data for operations like FS_WRITE. After allocating the buffers, it makes a
- special call to the IFS, which sets up a GDT alias for itself (we need to use
- GDT selectors because the IFS can be called in the context of any process). In
- more detail, what we do is:
-
- When the IFS loads
-
- Call the AllocGDTSelector DevHlp to allocate two GDT selectors. These will be
- the selectors used by the IFS to get access to the control program's two
- buffers. We allocate them now because GDT selectors can only be allocated at
- initialization time.
-
- When the control program loads
-
- o Call DosAllocMem() to allocate memory for the two buffers to communicate
- between the IFS and the control program.
-
- o Call the IFS via DosFSCtl() and pass the addresses of the two buffers.
-
- o The IFS calls the VMLock DevHlp to lock the buffers permanently into memory
- (we need to do this because the next call requires it).
-
- o Call the LinToGDTSelector DevHlp to map the memory to the GDT selectors we
- allocated when the IFS loaded.
-
- This isn't the only way we could've implemented this. We could've had the IFS
- allocate the memory, for example, instead of the control program. It really
- comes down to personal preference, because either works just as well.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.4. A Shared Memory Protocol ΓòÉΓòÉΓòÉ
-
- Once the buffers are allocated and accessible to both the ring 0 and ring 3
- code, we need to set up some kind of protocol for its use. The control program
- needs to know when a valid operation is in the buffers and ready to be
- performed. The IFS needs to know when the buffers are in use, and when the
- buffers contain the results of a completed operation. Again, there are several
- ways to implement this. The method I chose involves using semaphores and
- captive threads.
-
- After the control program allocates the buffers and does any other
- initialization, it calls the IFS through DosFSCtl(). The IFS sets up the ring
- 0 GDT aliases for the buffers, and then suspends the control program's thread
- by making it wait on a semaphore (thus capturing it). To the control program,
- it just looks like it made a system call that is taking a very long time.
-
- When a request comes in to the IFS on another thread, it places the parameters
- and data into the two buffers and releases the semaphore that the control
- program's thread is blocked on. When that thread starts running again, the IFS
- returns from the DosFSCtl() call to the control program, where it executes the
- operation and places the results back into the buffer. It then calls the IFS
- again, which blocks the control program on the semaphore and starts the whole
- process over again.
-
- The advantage of this approach is that whenever the control program is running,
- it is guaranteed to have a valid operation in the buffer waiting to be
- executed. Thus you never have to worry about semaphores in the control
- program. This is especially nice because 16-bit and 32-bit semaphores are
- incompatible.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.5. The Semaphores ΓòÉΓòÉΓòÉ
-
- Even though the control program doesn't have to worry about semaphores, the IFS
- certainly does, and in a big way. It has to worry about serializing all the
- requests it gets, and handling things like the control program unexpectedly
- terminating. To do this, we employ four semaphores:
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéName ΓöéMnemonic ΓöéStates Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéCPAttached ΓöéControl Program Attached Γöé-1 = never attached, 0 = Γöé
- Γöé Γöé Γöénot currently attached, 1Γöé
- Γöé Γöé Γöé= attached Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéBufLock ΓöéShared buffers are lockedΓöéClear = buffers not Γöé
- Γöé Γöé Γöélocked, Set = buffers areΓöé
- Γöé Γöé Γöélocked Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéCmdReady ΓöéCommand ready to execute ΓöéClear = command ready, Γöé
- Γöé Γöé ΓöéSet = command not ready Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéCmdComplete ΓöéCommand is complete ΓöéClear = command is Γöé
- Γöé Γöé Γöécomplete, Set = command Γöé
- Γöé Γöé Γöénot complete Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- CPAttached is used to indicate whether the control program is currently
- attached to the IFS. A value of -1 indicates that it has never attached to the
- IFS, 0 means it currently is not attached, but has been in the past, and 1
- means it currently is attached. This semaphore is unique in that it is not a
- system semaphore, but an int that is being used as a semaphore. The reason we
- need to implement it this way will become clear when we start discussing the
- code.
-
- BufLock is used to serialize requests to the IFS. Whenever the IFS gets a
- request, the request thread blocks on this semaphore until it's clear, at which
- time it knows that its OK to use the shared buffers to initiate the next
- operation.
-
- CmdReady is the semaphore used to tell the control program that a request is in
- the shared buffers and is ready to execute. The control program thread blocks
- on this semaphore; a request thread clears this semaphore when a request is
- ready.
-
- CmdComplete indicates to the request thread that the command it initiated is
- complete and that the results are in the shared buffers. It is cleared by the
- control program thread when it calls back into the IFS after it completes an
- operation.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.6. IFS Initialization ΓòÉΓòÉΓòÉ
-
- When OS/2 is booting and finds an IFS= line in the CONFIG.SYS, it will check
- that the file specified is a valid DLL and that it exports all of the required
- entry points for IFS's. If it is not a valid IFS, OS/2 will put up a message
- and refuse to load it. If the IFS is valid, OS/2 will load it into global
- system memory and then initialize it by calling FS_INIT (note that if the IFS
- has a LibInit routine, it will be ignored).
-
- RING0\R0COMM.C contains the code for the FS_INIT routine. Just like device
- drivers, IFS's get initialized in ring 3. Because of the special state of the
- system, an IFS can make calls to a limited set of Dos APIs (see table 1 for a
- list of which ones are allowed). It can also call any of the DevHlp routines
- that are valid at initialization time, but it cannot call any of the file
- system helpers.
-
- FS_INIT gets passed a pointer to the parameters on the IFS= line and a pointer
- to the DevHlp entry point. The third parameter is used to communicate between
- the IFS and the system's mini-IFS; we can safely ignore it.
-
- The first thing our IFS does is call DosPutMessage() to put up a sign-on
- message (it's a good idea to put up a message like this while you are still
- debugging the IFS, but you should take it out in release versions). After the
- sign-on banner is printed, we call a special routine to initialize the C
- runtime environment. This is a stripped down version of the startup code that
- comes with Borland C++; all it does is zero the BSS area and call any #pragma
- startup routines. Strictly speaking, it is probably not necessary.
-
- Next we save any parameters that were on the IFS= line in a global buffer and
- save the address of the DevHlp entry point. Note that contrary to what the IFS
- reference says, we have to check the szParm pointer before using it because it
- will be NULL if there are no parameters. The reference leads you to believe
- that it will point to an empty string, but that isn't true.
-
- Next we allocate a small block of memory in the system portion of the linear
- address space with the VMAlloc DevHlp (the system portion is global to all
- processes, just like GDT selectors). This memory will be used to hold the two
- lock handles that are created by the VMLock DevHlp when we lock down the memory
- that is shared between the control program and the IFS. We have to allocate
- the lock handles in the linear address range because VMLock can only put its
- lock handles there. Since our code is 16-bit, the compiler doesn't know what a
- linear address is. We deal with them by creating a new typedef, LINADDR, which
- is just an unsigned long.
-
- Next we also allocate two GDT selectors to alias the shared memory on the ring
- 0 side. This is done here because according to the PDD reference, you can only
- allocate GDT selectors at initialization time (in fact, if you do it after
- initialization, it still works, but why take the chance, right ?). We then
- create pointers out of the GDT selectors and assign them to the two global
- variables used to access the shared buffers. Note that at this point, no
- memory is allocated! We have our pointers set up, but if we were to try and
- access them, we'd get a TRAP D. We must wait for the control program to start
- and call the IFS before we can put memory behind those GDT selectors.
-
- After that's done, we set CPAttached to -1, which says that the control
- program has never attached to the IFS. We'll see later why its important to
- distinguish between when it has never attached, and when it has attached but
- then detached.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.7. Control Program Flow ΓòÉΓòÉΓòÉ
-
- RING3\R3COMM.C contains the code to startup the control program. It first
- prints a banner, just like the IFS, and then allocates and commits memory for
- the two buffers. Once that is done, it puts the pointers to the two blocks of
- memory in the structure that is passed to the IFS for initialization. Before
- we call the IFS, though, we make a copy of the file system name in a temporary
- buffer. The DosFSCtl() call can use three different methods to figure out
- which IFS to call; we want to use the method where we specify the IFS's name.
- To do that we have to make a temporary copy of the IFS name because DosFSCtl
- could modify the buffer that contains the IFS name.
-
- Once all the preparations are made, the control program calls the IFS to
- initialize. To the control program it's really no big deal - just one
- DosFSCtl() call. When the DosFSCtl() returns, it will either be because there
- was an initialization error, or there was an operation waiting in the shared
- buffers to be executed. If an error occurred, we just terminate the control
- program (perhaps a more user friendly error message should be printed, but
- after all, this is just a framework). If it returned because an operation is
- ready, we enter the dispatch loop.
-
- The dispatch loop figures out what operation was requested, and calls that
- routine to execute it. Right now we only support the attach routine (which is
- actually just a stub that returns NO_ERROR). If it gets a request for an
- operation it doesn't understand, it prints an error message and returns
- ERROR_NOT_SUPPORTED to the IFS.
-
- Once the operation has been executed, we again copy the IFS name into a
- temporary buffer and make a DosFSCtl() call to indicate that this operation is
- complete, the results are in the shared buffer, and we're ready for the next
- request. When that DosFSCtl() returns, another operation will be waiting in
- the shared buffer.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.8. Ring 0 Side of Control Program Initialization ΓòÉΓòÉΓòÉ
-
- As mentioned above, the ring 3 side of the control program initialization is
- very simple. The ring 0 side is a little more complicated, though. FS_FSCTL in
- RING0\R0COMM.C contains the code for the initialization. FS_FSCTL is used to
- provide an architected way to add IFS specific calls (sort of like the IOCTL
- interface for devices). There are three standard calls, which we just ignore
- for now. To those we add two new calls, FSCTL_FUNC_INIT and FSCTL_FUNC_NEXT.
- FSCTL_FUNC_INIT is called by the control program when it initializes.
- FSCTL_FUNC_NEXT is called when the control program has completed an operation
- and its ready for the next one.
-
- When FSCTL_FUNC_INIT is called, the first thing we do is check to see if the
- control program is already attached. If it is, we return an error code (this
- scenario could happen if the user tries to start a second copy of the control
- program). If the control program isn't already running, we wait until the
- BufLock semaphore is cleared. We do this because theoretically, we could run
- into the following situation: a request comes into the IFS and it starts
- servicing it. The control program is then detached, and then a new copy is run
- and tries to attach. The IFS is still in the middle of trying to service that
- request, however, and hasn't yet noticed the control program detached in the
- first place. It could be really bad if that ever did happen because the shared
- buffers would be corrupted, so we explicitly wait until the BufLock semaphore
- is clear, meaning that there are no threads using the shared buffers. We have
- to surround this with a check to see if the control program has ever been
- attached, because if it hasn't, the BufLock semaphore will not be initialized.
-
- Next we verify that the buffer that was passed to us is the proper size and
- that it is addressable. We have to check addressability on everything that is
- passed in from a ring 3 program because if it is not addressable, we bring down
- the whole entire system.
-
- Once addressability has been verified, we lock down the operation parameter
- area, and put the returned lock into the memory we allocated at FS_INIT time.
- Once that is done, we map the memory to the GDT selector that we allocated at
- FS_INIT time. We then do the same for the data buffer. Once these operations
- are complete, the memory can be shared between the IFS and the control program.
-
- Once that is complete, we clear the BufLock semaphore to initialize the
- semaphore that indicates that the shared buffer is not being used by anyone.
- We then get the process ID of the control program. This is used by the FS_EXIT
- routine. FS_EXIT is called whenever any process terminates. We have it check
- the process ID of the process that is terminating against the process ID of the
- control program, so that if the control program unexpectedly terminates, we
- detach it properly.
-
- After all that initialization is completed, CPAttached is set to 1 to indicate
- that the control program is attached. We then fall through to FSCTL_FUNC_NEXT.
- Since this function will be called every time an operation is completed, we
- first ensure that the control program is attached. If it's not, we return an
- error code. If it is attached, we first set the CmdReady semaphore to indicate
- that a command is no longer in the shared buffers (instead, results are in the
- buffers). We then clear CmdComplete to unblock the requesting thread (letting
- it know that its results are waiting). We then wait on the CmdReady semaphore,
- which will be cleared when a new operation is put into the shared buffers.
-
- At any time, any of the semaphore calls could return ERROR_INTERRUPT if the
- user is trying to kill the control program. If that occurs, we detach the
- control program before returning the error code.
-
- To detach the control program, we have to first set CPAttached to 0. We have to
- do it first to avoid possible deadlocks. We then unlock the shared memory
- buffers; if we don't do this, the control program will appear to die, but you
- will never be able to get rid of its window. Finally, we clear the CmdComplete
- semaphore so that if there is a request in progress, the requesting thread will
- unblock.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.9. An Example Call: Attaching a Drive ΓòÉΓòÉΓòÉ
-
- Before you can use a drive managed by your IFS, you have to attach it. This
- creates an association between a drive letter and the IFS. RING3\FSATT.C
- contains an example program that attaches a drive. It is basically a front end
- to the DosFSAttach() and DosQueryFSAttach() calls. With a little help from the
- Control Program Programming Reference, you should be able to figure it out
- easily.
-
- The part that needs more explaining is the ring 0 side of the interface. When
- you issue a DosFSAttach() or DosQueryFSAttach(), the file system router calls
- the IFS's FS_ATTACH entry point (this can be found in RING0\R0STUBS.C). This
- code is basically a prototype for all of the FS_* calls that the IFS handles.
- It serializes access to the control program, does some preliminary validation
- of the parameters, sets up the argument block and passes it to the control
- program, waits until the control program executes the operation, and then
- returns the results of the operation. Once the details of this call are
- understood, all the others can be written pretty easily.
-
- The first thing FS_ATTACH does is check to see if the control program is
- attached; if it isn't, it immediately returns an error code. If the control
- program is attached, it waits until it can get access to the shared buffers.
- It is possible to time out waiting for this access; if we do, we return an
- ERROR_NOT_READY return code to the caller.
-
- Once we have access to the shared buffers, we wait until the control program
- completes the last operation it started. We have to do this because it is
- possible for a thread to give the control program a request to service, and
- then time out waiting for it to complete it. We could then have another thread
- come along and try to start a new request, but if the control program hasn't
- finished the last one yet, the shared buffers will get trashed because the IFS
- will be trying to put a new operation in them, and the control program will be
- trying to put the results of the last operation in them. Therefore we must
- wait until the control program has finished the last operation.
-
- Once those verifications are completed, we check to make sure we can access the
- buffer that was passed in. For an attach or detach request, all we have to do
- is check for readability, but for the query attach request, we have to check
- writability.
-
- We then check that the control program is still attached. This check is
- crucial because during any of those semaphore or FSH_PROBEBUF calls we could've
- blocked, and the control program could've terminated. If it did, the shared
- buffers are no longer valid, and if we try to access them we will trap. It's
- for this reason that the CPAttached semaphore is an int and not a system
- semaphore - the semaphore calls don't guarantee that they won't block (i.e.
- they could block). To make absolutely sure, the only thing we can rely on is a
- semaphore implemented as an int (it's probably worthwhile to refresh your
- memory here that ring 0 code will never be multitasked - you have to explicitly
- give up the CPU).
-
- Once we have verified that the control program is still attached, and thus our
- shared buffers are still valid, we setup the shared buffers with the
- operation's parameters. You can refer to R0R3SHAR.H (in either RING0 or RING3)
- for the data structure used. After that's complete, we clear the CmdReady
- semaphore to unblock the control program and indicate to it that a request is
- ready to be executed. We then block on CmdComplete waiting for the control
- program to execute our request. We specify a time-out to the wait so that we
- never get hung up on a faulty control program (if you never want to time out,
- you can change the value of MAXCPRESWAIT to -1). If we should time out, we
- release our hold on the shared buffer by clearing BufLock, and then return
- ERROR_NOT_READY.
-
- After the wait returns and we check for a time out, we also check to make sure
- the control program is still attached. It is possible that while the control
- program was executing our request that it terminated (maybe we had a bug that
- caused it to trap). If so, the shared buffers are no longer accessible, so we
- return an error code to the caller. If all went well, we copy the results out
- of the result buffers. Note that while we are doing this, we can't do anything
- that could cause us to yield because the control program could terminate during
- that time.
-
- After we copy the results out, we free up out hold on the shared buffers by
- clearing the BufLock semaphore and then return the error code that the control
- program told us to return.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.3.10. And That's About It ΓòÉΓòÉΓòÉ
-
- That about covers the communications between the ring 0 and ring 3 sides of an
- IFS. If you're daring, you now have all the basics to forge ahead and begin
- implementing this type of IFS. If this still seems a little scary, don't worry
- - in the next article I'll fill in all the rest of the routines to give you a
- true skeleton to work with, and start discussing how to implement the FS_*
- calls. I will also provide a state diagram that shows all of the various
- states the system can be in, along with the states of the semaphores, to show
- that no deadlocks will occur in the IFS no matter what happens (this is
- actually very important because a deadlock is extremely difficult to track
- down, so you're better off investing time up front making sure they will never
- occur than beating your head against a wall later trying to track one down).
-
- I'd like to thank everyone who has written to encourage me to continue the
- series or with ideas for topics you'd like me to cover. Since the only pay I
- receive is your feedback, I hope you'll continue to write.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ <hidden> Dos APIs Callable at Initialization Time ΓòÉΓòÉΓòÉ
-
- The following Dos APIs are callable by the IFS at initialization time:
-
- o DosBeep
- o DosChgFilePtr
- o DosClose
- o DosDelete
- o DosDevConfig
- o DosFindClose
- o DosFindFirst
- o DosFindNext
- o DosGetEnv
- o DosGetInfoSeg
- o DosGetMessage
- o DosOpen
- o DosPutMessage
- o DosQCurDir
- o DosQCurDisk
- o DosQFileInfo
- o DosQSysInfo
- o DosRead
- o DosWrite
-
-
- ΓòÉΓòÉΓòÉ 4.4. Programming the Container Control - Part 3 ΓòÉΓòÉΓòÉ
-
- Written by Larry Salomon, Jr.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.1. Back at the Batcave ΓòÉΓòÉΓòÉ
-
- Last month we continued our disection of the container control and how to use
- it. The tree view was added to our list of conquests, and we started
- developing a sample application which we will continue to use. This month, we
- will add more meat to the bones of our skeleton by learning about the detail
- view and direct editing, among other things.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.2. Detail View ΓòÉΓòÉΓòÉ
-
- Back in the first installment of this series, the detail view was described in
- the following manner.
-
- Each object is represented as a detailed description of the object. The
- information displayed is defined by the application.
-
- While I realize that did not say much, it served to illustrate that the detail
- view is the most flexible of the views, in terms of what can be displayed. It
- should be logical then to assume that this means yet more setup on the part of
- the application.
-
- What is the Detail View?
-
- To be precise, the detail view is a matrix view of the contents of a container,
- where each row in the matrix is a separate object and each column is an
- attribute (called a field) of every object to be displayed.
-
- Since the objects are already added using the CM_ALLOCRECORD/CM_INSERTRECORD
- messages, the columns must be added; this is done using the
- CM_ALLOCDETAILFIELDINFO/CM_INSERTDETAILFIELDINFO messages. As with its
- record-oriented counterpart, the CM_ALLOCDETAILFIELDINFO accepts the number of
- fields to allocate memory for and returns a pointer to the first FIELDINFO
- structure in the linked-list.
-
- typedef struct _FIELDINFO {
- ULONG cb;
- ULONG flData;
- ULONG flTitle;
- PVOID pTitleData;
- ULONG offStruct;
- PVOID pUserData;
- struct _FIELDINFO *pNextFieldInfo;
- ULONG cxWidth;
- } FIELDINFO, *PFIELDINFO;
-
- Figure 1. The FIELDINFO structure.
-
- cb specifies the size of the structure in bytes.
-
- flData specifies flags (CFA_* constants) for the field, especially
- the datatype.
-
- flTitle specifies flags (CFA_* constants) for the column title.
-
- pTitleData points to a string used for the column heading (can be
- NULL).
-
- offStruct specifies the offset of the data in the container record to
- be formatted according to its datatype. The FIELDOFFSET
- macro (defined in the Toolkit) is very helpful in
- initializing this field.
-
- When the datatype is CFA_STRING, the field in the container
- record is expected to be a pointer to the string and not
- the string itself. For example,
-
- typedef struct _MYCNRREC {
- MINIRECORDCORE mrcCore;
- CHAR achText[256];
- ULONG ulNumSold;
- float fGrossIncome;
- float fNetIncome;
- float fTotalCost;
- float fNetProfit;
- CHAR achProdName[256];
- PCHAR pchProdName;
- } MYCNRREC, *PMYCNRREC;
- we would specify FIELDOFFSET(MYCNRREC,pchProdName) instead
- of FIELDOFFSET(MYCNRREC,achProdName). The reason for this
- will be clear when we discuss direct editing.
-
- pUserData points to any application-defined data for the field.
-
- pNextFieldInfo points to the next FIELDINFO structure. This is
- initialized by the CM_ALLOCDETAILFIELDINFO message.
-
- cxWidth specifies the width in pixels of the field. This is
- initialized by the CM_ALLOCDETAILFIELDINFO message to 0,
- indicating that the field should be wide enough to show the
- widest value. If the default is not used and the data is
- too wide to fit, it is truncated when displayed.
-
- The flData field is initialized using one or more CFA_* constants:
-
- Data type
-
- CFA_BITMAPORICON offStruct "points" to the handle of a bitmap or icon,
- depending on whether or not CA_DRAWICON or CA_DRAWBITMAP
- was specified in the flWindowAttr field in the
- CM_SETCNRINFO message (CA_DRAWICON is the default if not
- explicitly changed by the application).
-
- CFA_STRING offStruct "points" to a pointer to the string to be
- displayed. Only data of this type can be directly edited.
-
- CFA_ULONG offStruct "points" to an unsigned long integer.
-
- CFA_DATE offStruct "points" to a CDATE structure.
-
- CFA_TIME offStruct "points" to a CTIME structure.
-
- For the latter three, NLS support is provided automatically by the container.
- You should note that there is no support for short integers, since they map
- directly to long integers with no loss in precision, nor is there support for
- floating point (none of PM uses floating point, so why should they start now).
- The latter means that you have to also have a string representation of the
- number (and creates all kinds of headaches if you will allow editing of the
- value).
-
- Alignment
-
- CFA_LEFT Align the data to the left
-
- CFA_CENTER Horizontally center the data
-
- CFA_RIGHT Align the data to the right
-
- CFA_TOP Align the data to the top
-
- CFA_VCENTER Vertically center the data
-
- CFA_BOTTOM Align the data to the bottom
-
- Miscellaneous
-
- CFA_SEPARATOR Displays a vertical separator to the right of the field
-
- CFA_HORZSEPARATOR Displays a horizontal separator underneath the column
- heading
-
- CFA_OWNER Enables ownerdraw for this field
-
- CFA_INVISIBLE Prevents display of this column
-
- CFA_FIREADONLY Prevents direct editing of the data if CFA_STRING is the
- datatype
-
- The flTitle field is initialized using one or more of the alignment fields
- and/or one or both of the following
-
- Miscellaneous
-
- CFA_BITMAPORICON pTitleData is the handle of a bitmap or icon, depending on
- whether or not CA_DRAWICON or CA_DRAWBITMAP was specified
- in the flWindowAttr field in the CM_SETCNRINFO message
- (CA_DRAWICON is the default if not explicitly changed by
- the application). If this is not specified, pTitleData is
- expected to point to character data.
-
- CFA_FITITLEREADONLY the text of the title is not directly editable.
-
- What's Next?
-
- Once you have initialized all of the FIELDINFO structures, you can "insert"
- them into the container using the CM_INSERTDETAILFIELDINFO message. Again
- using the parallel of the CM_INSERTRECORD message, it expects a pointer to the
- first FIELDINFO structure as well as a pointer to a FIELDINFOINSERT structure.
-
- typedef struct _FIELDINFOINSERT {
- ULONG cb;
- PFIELDINFO pFieldInfoOrder;
- ULONG fInvalidateFieldInfo;
- ULONG cFieldInfoInsert;
- } FIELDINFOINSERT, *PFIELDINFOINSERT;
-
- Figure 2. The FIELDINFOINSERT structure.
-
- cb specifies the size of the structure in bytes.
-
- pFieldInfoOrder specifies the FIELDINFO structure to be linked after, or
- CMA_FIRST or CMA_LAST to specify that these FIELDINFO
- structures should go to the head/tail of the list,
- respectively.
-
- fInvalidateFieldInfo specifies whether or not the fields are to be invalidated.
-
- cFieldInfoInsert specifies the number of FIELDINFO structures being
- inserted.
-
- Finally, changing the view to detail view is as simple as - you guessed it -
- sending the control a CM_SETCNRINFO message.
-
- CNRINFO ciInfo;
-
- ciInfo.flWindowAttr=CV_DETAIL;
- WinSendMsg(hwndCnr,
- CM_SETCNRINFO,
- MPFROMP(&ciInfo),
- MPFROMLONG(CMA_FLWINDOWATTR));
-
- Figure 3. Changing to the detail view.
-
- Note that, even if you initialize the pTitleData field of the FIELDINFO
- structure to point to the column heading, the titles are not displayed unless
- you specify CA_DETAILSVIEWTITLES in the flWindowAttr field.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.3. Direct Editing ΓòÉΓòÉΓòÉ
-
- Direct editing is accomplished by pressing the proper combination of keys
- and/or mouse buttons as defined in the "Mappings" page of the "Mouse"
- settings (in the "OS/2 System"/"System Setup" folder) while the mouse is over a
- directly-editable region. When this is done, a multi-line edit control appears
- and is initialized with the current text, in which you can make your changes;
- the enter key acts as a newline, while the pad enter key completes the editing
- operation and (normally) applies the changes.
-
- From a programming perspective, three notifications are sent to the application
- whenever direct-editing is requested by the user when over a non-read-only
- field ("field" is used here to mean any text string and not as it was defined
- in the discussion of the detail view) - CN_BEGINEDIT, CN_REALLOCPSZ, and
- CN_ENDEDIT (in that order). For all three, mpParm2 points to a CNREDITDATA
- structure which describes the state of the record being edited. The purpose of
- CN_BEGINEDIT and CN_ENDEDIT is to notify the user that editing is about to
- begin/end. However, only the CN_REALLOCPSZ is important, since the former two
- can be ignored while the latter cannot.
-
- typedef struct _CNREDITDATA {
- ULONG cb;
- HWND hwndCnr;
- PRECORDCORE pRecord;
- PFIELDINFO pFieldInfo;
- PSZ *ppszText;
- ULONG cbText;
- ULONG id;
- } CNREDITDATA;
-
- Figure 4. The CNREDITDATA structure.
-
- cb specifies the size of the structure in bytes.
-
- hwndCnr specifies the handle of the container.
-
- pRecord points to the record being edited.
-
- pFieldInfo points to the FIELDINFO structure describing the field
- being edited.
-
- ppszText points to the pointer to the text being edited.
-
- cbText specifies the size of the text.
-
- id specifies which part of the container contains the text to
- be edited and can be one of the following:
- CID_CNRTITLEWND, CID_LEFTDVWND, CID_RIGHTDVWND,
- CID_LEFTCOLTITLEWND, or CID_RIGHTCOLTITLEWND.
-
- The CN_REALLOCPSZ indicates that editing is about to end and that the
- application should allocate a new block of memory to contain the text.
- ppszText double-points to the old text and cbText specifies the length of the
- new text. If a new memory block is allocated, the pointer to the new memory
- block must be stored in ppszText. Returning TRUE from this notification
- indicates that ppszText points to a memory block sufficiently large enough to
- hold cbText bytes and that the container should copy the new text to this
- buffer. (I am not sure if cbText includes the null terminator - `\0')
- Returning FALSE indicates that the changes should not be copied and should be
- discarded.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.4. Altered States ΓòÉΓòÉΓòÉ
-
- As defined by CUA '91 (I think), an object in general can be in one or more of
- five states (or none at all) - source, target, in-use, cursored, and selected.
- A container record stores information on its current state in the flRecordAttr
- (in both the RECORDCORE and MINIRECORDCORE structures) in the form of CRA_*
- constants. Setting the state, however, is not a simple matter of setting this
- field, since the container will have no way of knowing that you've changed the
- field. Instead, you send the container a CM_SETRECORDEMPHASIS message which
- updates this field in the record and updates the display of that record on the
- screen.
-
- Those who are "on the ball" will notice that there is no CRA_SOURCE constant
- defined in the 2.0 Toolkit. This was inadvertently left out and should be
- defined to be 0x00004000L in pmstddlg.h.
-
- So what do all of these states mean?
-
- CRA_CURSORED the record has the input focus.
-
- CRA_INUSE the record (and thus the object) is in use by the
- application.
-
- CRA_SELECTED the record is selected for later manipulation.
-
- CRA_SOURCE the record is a source for a direct-manipulation operation.
-
- CRA_TARGET the record is a target for a direct-manipulation operation.
-
- When you want to query all records with a particular emphasis type, you use the
- CM_QUERYRECORDEMPHASIS message. This returns the next record that has the
- specifies emphasis (or NULL if none exists).
-
- Popup Menus
-
- If you take a close look at the Workplace Shell, you will see all of these
- states used in one way or another. A more interesting use is in conjunction
- with popup menus; if the record underneath the mouse is not selected, it alone
- is given source emphasis. If it is selected, all records that are selected are
- given source emphasis. If no record is underneath the mouse, the container
- itself is given source emphasis. After the appropriate record states have been
- changed, WinPopupMenu() is called. Finally, the WM_MENUEND message is
- intercepted to "un-source" the records that were changed. Broken down into
- pseudo-code, this becomes:
-
- 1. Determine if the mouse is over a container record
-
- o If so, check the selection state
-
- - If the record is selected, add source emphasis to all selected records
- - If the record is not selected, give it source emphasis only
-
- o If not, select the enter container
-
- 2. Call WinPopupMenu()
- 3. Undo source emphasis changes
-
- While determining if the mouse is over a record is easy when processing the
- WM_CONTROL message, it is a bit more difficult when in the WM_CONTEXTMENU menu.
- The solution, it would appear from looking at our arsenal of messages that we
- can send to the container, would be to send the container a
- CM_QUERYRECORDFROMRECT message, specifying the mouse position as the rectangle
- to query. Looking a bit closer at the documentation reveals that the rectangle
- has to be specified in virtual coordinates. What???
-
- Virtual Coordinates
-
- Okay, okay, everyone has probably heard of and is vaguely familiar with virtual
- coordinates, or else you would not be in PM programming to begin with. The
- container's notion of the origin in its coordinate system is somewhat awry,
- unfortunately, and this confuses things; the origin is defined to be the screen
- coordinate of the lower left corner of the container at the time the last
- CM_ARRANGE message was sent.
-
- So, you either have to keep track of when you send the container a CM_ARRANGE
- message and perform all sorts of hocus pocus to remember where the origin is
- supposed to be, or you can finish reading this sentence and discover that the
- documentation for CM_QUERYRECORDFROMRECT is flat-out wrong. The rectangle
- specified in this message is in window coordinates. Whew! That greatly
- simplifies things, except that when in detail view the record returned is the
- one above the one the mouse is over. Oh boy. Fortunately, we can calculate
- the height of a record using the CM_QUERYRECORDRECT message, which we use to
- adjust the mouse position before calling CM_QUERYRECORDFROMRECT.
-
- Now that we have the record underneath the mouse, we can check its selection
- state by examining the flRecordAttr field. If the record is selected, it is
- probably more efficient to use the CM_QUERYRECORDEMPHASIS message to get all
- selected records, but we already have this exquisite recursive search function,
- so I used that instead. Another example of poor documentation is in
- CM_SETRECORDEMPHASIS where it does not tell you that you can set the
- container's source emphasis by specifying NULL for the record.
-
- Finally, we call WinPopupMenu() and undo the source emphasis and - voila! -
- we're done.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.5. CNR3 - A Sample Application Revisited ΓòÉΓòÉΓòÉ
-
- CNR3 builds upon CNR2 by adding detail view support, direct editing support,
- and "proper" popup menu support. As with part II, landmarks have been added to
- CNR3.C which are to point out things of interest. These landmarks are
- described below.
-
- Landmark 1
-
- This is to point out the additions of the last four fields to the MYCNREDIT
- structure and the addition of the pmcrMenu field to the CLIENTDATA structure.
-
- Landmark 2
-
- This points out the allocation, initialization, and insertion of the FIELDINFO
- structures.
-
- Landmark 3
-
- This points out the new procedure for handling the context menu.
-
- Landmark 4
-
- This points out the correction for the bug in the CM_QUERYRECORDFROMRECT
- message when in details view as described above.
-
- Landmark 5
-
- This points out the processing of the CN_REALLOCPSZ notification.
-
- Landmark 6
-
- This points out the addition of the detail view menu item.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.4.6. Summary ΓòÉΓòÉΓòÉ
-
- This month we learned a lot of things, namely how to setup the details view,
- how direct editing is performed and what the container expects from the
- application with regards to this, and how selection states are set, queried,
- and used. We also saw how inadequate the documentation is when it contains so
- many examples of incorrect or incomplete information.
-
- Now you have enough information to use the container well. However, we're not
- done yet; next month, I will try to figure out some of the more advanced
- capabilities of the container such as record sharing and deltas. Stay tuned,
- same Bat-time, same Bat-channel!
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5. A Review of C++ Compilers ΓòÉΓòÉΓòÉ
-
- Written by Gordon W. Zeglinski
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.1. Introduction ΓòÉΓòÉΓòÉ
-
- This article, examines various real-world aspects of the primary C++ compilers
- available for OS/2. The compilers included in this review are:
-
- Borland C++ for OS/2 version 1.0
- Watcom C/C++ version 9.5
- IBM Cset++ version 2.0
- EMX/gcc version 0.8g
-
- I have omitted Zoretch C++ from this list because I do not have access to this
- compiler. The last time I looked at this compiler, it did not include an OS/2
- debugger.
-
- These compilers will be compared on the bases of:
-
- o Time to compile the test code
- o Execution time of the test code
- o Size of the resultant .EXE file
- o Quality of bundled tools
- o Bugs found
-
- About the Tests
-
- The test code consists of a series of matrix objects developed by the author.
- These objects rely on both floating point operations and list manipulations
- (integer math, pointer dereferencing, etc.). The object hierarchy makes
- extensive use of virtual, pure virtual, and inline "functions". "Functions" in
- this case refer to both operators and functions.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.2. Compiler Overview ΓòÉΓòÉΓòÉ
-
- In this section, I will examine the non-quantitative aspects of the various
- compilers, i.e. how easy they are to install, ease of use, and quality of the
- support tools. Given this, one should keep in mind that the following
- discussion is subjective and, as such, is the opinion of the author.
-
- Borland C++ for OS/2 version 1.0
-
- This compiler is very similar to its windows counter part. Its IDE uses the
- same basic design and the windows version. The package comes with both a
- command line and PM-based compiler, a debugger, and documents on OS/2
- programming in .INF format. Also, various on-line documents are provided to
- help use the the tools.
-
- I have found several bugs in the compiler. The following list is by no means
- extensive.
-
- 1. The editor in the IDE has a tendency to drop line feed characters every so
- often this leads to the occasional hard to find syntax error.
-
- 2. None of the PM functions are accessible using the <CTRL><F1> help hotkeys
- from within the IDE.
-
- 3. The compiler has problems filling in virtual function tables under certain
- instances. It leaves them as NULL. The results of calling a function in
- this state is a protection violation error.
-
- 4. The debugger is next to unusable in my opinion. When debugging C++
- programs (especially PM programs), one can expect to reboot their systems
- very often. This is due to OS/2's single threaded message queue and the
- inability to kill the debugger via repeated <CTRL><ESC>'s.
-
- 5. TLINK is unable to properly handle segments with IOPL permission, resulting
- is a protection violation. There was a work around for this problem, but I
- have not tried it because bug #3 prevents me from using this compiler in
- the application that needs IOPL priviledges.
-
- The Resource Workshop that ships with this version is similar to its Windows
- counterpart but lack much of its nice features. For instance, when editing
- menus one is simply typing a resource script into a large entry field control.
- The only resources that are edited visually are the dialog boxes, bitmaps and
- icons; however, the icons no longer work under OS/2 2.1 and the bitmap editor
- has some bugs in it that cause stray pixels to appear. The dialog editor is
- great, though, and is far better than the one IBM supplies with CSet++.
-
- This version lacks OWL and the profiler which ships with its DOS/Windows
- counterpart. On the positive side, this is a fast compiler. It compiles
- source files faster than any other compiler tested. Also, it seems that there
- has been some bugs fixed in its optimizer because code that would bomb under
- the DOS compiler when optimized now works under the OS/2 compiler.
-
- Tech support from Borland is available through Compuserve. I have heard that
- they no longer provide tech support to Internet mail addresses but cannot say
- if this is true. Past experience with them was a little disappointing. If you
- report a bug that has been fixed, they will tell you about a patch if it
- exists. Bug fixes integrated into the product, though, are usually done in a
- future version, which you have to purchase to get these fixes.
-
- Watcom C/C++ version 9.5
-
- The Watcom compiler ships with a modified version of the OS/2 Toolkit version
- 2.0. It generates code for 32 bit DOS, Windows (with a DOS extender), NT and
- OS/2. If multi-platform code generation is a must for you, then this is the
- compiler you want. It includes a text mode debugger and profiler. Another plus
- for this package is that it is capable of optimizing for the Pentinum
- processor. Also included in the package is quite the hefty stack of
- documentation. However, in order to program in any of the above environments,
- one still has to buy the appropriate programming guides for the target
- operating systems. Shipped documentation includes:
-
- o WATCOM C/C++32. Optimizing User's Guide
- o WATCOM C/C++ Tools User's Guide
- o WATCOM VIDEO User's Guide
- o WATCOM VIDEO User's Guide Addendum
- o WATCOM Linker User's Guide
- o Supplement to WATCOM Linker User's Guide
- o WATCOM C Library Reference
- o WATCOM C++ Class Library Reference
- o WATCOM C++ Container Class Library Reference
- o WATCOM C Graphics Library Reference
- o The C++ Programming Language
- o WATCOM C Language Reference
- o WATCOM C/C++32 Commonly Asked Questions & Answers
-
- Although being a VIO mode app, the debugger is quite powerful. In addition to
- the typical features associated with a source-level debugger, it also allows
- debugger instructions to be executed at break points. However, there does not
- seem to be any C++ specific functionality, e.g. class browsers.
-
- The profiler included is also a VIO mode application and is divided into two
- separate parts: the sampler and sample displayer. The sampler uses the system
- clock to periodically interrupt the executing program and see where it is. It
- also allows the programmer to set "profile points" or "marks" within the
- source code, allowing it to be used as either an intrusive or non-intrusive
- profiler. Because the profiler does not use any device drivers, it is likely
- that under OS/2 the sample rate is only approximately 32 Hz, due to the fact
- that the profiler can only use the standard API calls to gain access to the
- timer interrupts.
-
- At any rate, the non-intrusiveness of the profiler is a negative point when it
- comes to profiling existing C++ code since in any OOP language, it is common to
- have many small functions that are frequently called. The only way to
- determine the impact of these functions is to place marks around them. For
- large amounts of code, this is undesirable because it has to be done manually.
- The sample displayer is pretty basic. It only gathers and displays time and
- frequency related data.
-
- One of the things which bothers me the most about the product is that the
- Watcom linker does not use standard .DEF files.
-
- In the few days that I have tested this package, the following bugs were found:
-
- 1. The compiler has problems dealing with the construct virtual operator=. I
- was able to work around this bug so that I could perform the benchmarks.
-
- 2. I could not get it to work properly with the Workframe version 1.1. This
- is probably due to the fact that I'm using the beta version of the
- Workframe from the last PDK until my copy of CSet++ arrives.
-
- Having found what I consider to be a serious bug (#1 above), I decided to give
- their tech support a try, provided through email. My first bug report was
- answered within 2 hours and subsequent email were all answered the same day.
- One day after sending them the code, I got a reply. Unfortunately for me,
- there is a grey area in the C++ "standards" that revolve around the use of
- virtual operator=(). Watcom follows the approach taken in MSC 7.0 which is
- different than just about every other C++ compiler. Watcom will be bringing
- this area to the attention of the ANSI C++ standards committee.
-
- IBM CSet++ version 2.0
-
- Now that my copy of the GA version of CSet++ has arrived, I can compare it to
- the release version of the others and to the beta version some of you may have.
- The package includes the OS/2 toolkit, IBM's Workframe, and the CSet++
- compiler. I'll concentrate on the compiler and it's support tools.
-
- The comparison of the GA to the BETA version of this compiler can be summarized
- in one sentence: the GA version compiles code about 2-3 times faster and it's
- tools are far more stable.
-
- One of the most important things (for some of my applications) about this
- compiler and the accompanying linker is that it is capable of interfacing with
- IOPL code segments. I have not tested Watcom's ability in this area. I also
- believe that the EMX package has input/output functions. Like Watcom, this
- compiler is compatible with version 3.0 of the C++ specifications, meaning that
- they support exceptions among other things. The Borland compiler does not and
- I'm not sure about the EMX package.
-
- The debugger is PM-based and has object browsing abilities built into it. It
- also has features which are specific to debugging PM-based programs (ie.
- monitoring message queues and such). My biggest problem with any PM-based
- debugger is that, if it is buggy, it can hang both the system queue and itself
- such that a reset is required. It does not appear to have the ability to
- program actions at breakpoints like the Watcom compiler does.
-
- After much use, the debugger performed almost flawlessly. I have found that it
- sometimes kills itself when the program monitor (a variable browser) is packed
- with variables. The best feature it has is its ability to save all of the
- settings and restore them when you resume debugging. These settings include
- breakpoints, user defined messages, etc. I have found a minor bug in its user
- defined messages - it did not properly display the message parameters after
- restarting the debugger although it did remember the messages I defined.
-
- The profiler is excellent, feature wise, and is PM-based. It is an intrusive
- analyzer that requires one to compile the code with both debugging info and
- profiling hooks turned on. The programmer can also insert profiling points
- within the code. The profiler is a full featured execution analyzer capable of
- measuring time, the number of times a profiler hook was called, and displaying
- a call tree. The time and frequency data can be displayed in a number of
- formats. The call tree displays which functions called who and the number of
- times these calls were made. It has problems, however; I have found that one
- of its display options will not function with a trace file I generated. Even
- worse is that some of its display modules do not support long filenames, which
- is unacceptable.
-
- The object browser is also quite useful; it allows a graphical and textual
- exploration of the classes used in the program. It displays the relationship
- between these objects by showing inheritance, who calls who, and class members.
-
- I have not used the PM object library that comes with this compiler because I
- am creating my own library. Others have complained that there is a lot of
- overhead in using this library, though, and that it takes along time to compile
- code that uses it.
-
- My biggest complaint about this product is its so-called documentation. I
- bought the 3.5" format package hoping to find tons of hard copy manuals. To my
- surprise, the hard copy documentation is very similar in size to the
- documentation that came with OS/2 2.0 GA. In several places, the hard copy
- documentation refers the reader to the on-line help. The only hard copy
- manuals with some thickness to them are:
-
- o Class Libraries Reference Summary
- o User Interface Class Library User's Guide (an IBM Red Book)
- o Programming Guide
-
- The rest of the manuals seem to have trivial content; if you were really stuck,
- you would typically be referred to the on-line help for the product or some
- other on-line file. There are also a few typo's in the manuals.
-
- Latest Bug Fixes
-
- My complaints about the lack of long filename support in EXTRA (the profiler)
- have been solved by applying CSD level 0001 to the package and then running the
- following little REXX program, which sets a flag in the EXTRA executables that
- allow them to see files with long names.
-
- Note: This REXX file assumes that the program EXEHDR.EXE is on the path (it is
- included with the toolkit).
-
- /* This exec addes the "newfiles" flag to the header of each of the
- Extra executables. This allows the user to use long names for trace
- files */
-
- "EXEHDR /NEWFILES IXTRA.EXE"
- "EXEHDR /NEWFILES ITIME.EXE"
- "EXEHDR /NEWFILES IEXCDENS.EXE"
- "EXEHDR /NEWFILES ICALNEST.EXE"
- "EXEHDR /NEWFILES ISTATS.EXE"
- "EXEHDR /NEWFILES IDCGRAPH.EXE"
-
- EMX/gcc version 0.8g
-
- The EMX/GNU compiler package is a very impressive freeware compiler. The
- package includes the GNU gcc version 2.4.5 compiler and a debugger. A bunch of
- other Unix-like tools are also included. The debugger is a VIO program which
- is command line driven. I haven't used it for PM programming or interfacing
- with OS/2's API. The docs for the package are available via ftp from the
- primary OS/2 FTP sites. The reader can get these documents for themselves if
- they so desire.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.3. Summary of Features ΓòÉΓòÉΓòÉ
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓöéBorland C++ forΓöéWatcom C/C++ ΓöéIBM CSet++ ΓöéEMX/gcc Γöé
- Γöé ΓöéOS/2 Γöé Γöé Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéMulti-Platform ΓöéNo Γöé32 bit OS/2, ΓöéNo ΓöéOS/2, DOS Γöé
- Γöé Γöé ΓöéDOS, Windows, Γöé Γöé Γöé
- Γöé Γöé ΓöéNT Γöé Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéDebugger ΓöéPM ΓöéVIO ΓöéPM ΓöéVIO Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéProfiler ΓöéNo ΓöéVIO ΓöéPM ΓöéNo Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéC++ Level Γöé2.1 Γöé3.0 Γöé3.0 Γöé2.1(?) Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPrecompiled Headers ΓöéYes ΓöéNo ΓöéYes ΓöéNo Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéTech Support Γöécompuserve ΓöéInternet email ΓöéInternet email ΓöéNo official Γöé
- Γöé Γöé Γöé Γöé Γöésupport Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.4. On with the Benchmarks ΓòÉΓòÉΓòÉ
-
- The benchmarking was performed on a 486 DX/33-based machine with 16M of RAM.
- The test consist of two programs both are related to my work on object oriented
- matrix classes. One test (the full matrix) is mostly floating point while the
- other (the sparse matrix) is a combination of list manipulation and floating
- point. Listed are the times it took to compile the two first test both with
- and without optimizations enabled is measured, the times it took to execute the
- each test program, and the size of the resulting executables.
-
- Note: in the following charts, (opt) means that optimization was turned on
-
- Compile Times
-
- These times are measured with a stopwatch and represent the time it took NMAKE
- or MAKE (in the case of EMX) to create the executable. The source code
- consists of approximately 11 files for each test.
-
- Note: For each table below, all times are in seconds and all sizes are in
- bytes.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓöéBorland ΓöéWatcom ΓöéIBM ΓöéEMX/gcc ΓöéBorland(opt)ΓöéWatcom(opt)ΓöéIBM(opt) ΓöéEMX/gcc(opt)Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéFull Matrix Γöé106 Γöé240 Γöé161 Γöé270 Γöé122 Γöé259 Γöé204 Γöé288 Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- Executable size
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓöéBorland ΓöéWatcom ΓöéIBM ΓöéEMX/gcc ΓöéBorland(opt)ΓöéWatcom(opt)ΓöéIBM(opt) ΓöéEMX/gcc(opt)Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéFull Matrix Γöé86549 Γöé137532 Γöé147328 Γöé176132 Γöé83477 Γöé145622 Γöé125552 Γöé118788 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéSparse Matrix Γöé113173 Γöé156712 Γöé171344 Γöé229380 Γöé107541 Γöé164775 Γöé147104 Γöé139628 Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- Execution Time
-
- The full test measures the time to LU decompose a 200 x 200 matrix. The sparse
- test measures the time to LU decompose and solve a 800 x 800 sparse matrix.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- Γöé ΓöéBorland ΓöéWatcom ΓöéIBM ΓöéEMX/gcc ΓöéBorland(opt)ΓöéWatcom(opt)ΓöéIBM(opt) ΓöéEMX/gcc(opt)Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéFull Matrix Γöé8 Γöé8.33 Γöé11 Γöé11.67 Γöé6.33 Γöé6.00 Γöé7.67 Γöé5.33 Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéSparse Matrix Γöé75.5 Γöé51.5 Γöé102.5 Γöé109 Γöé67.5 Γöé48.5 Γöé50.5 Γöé50.0 Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- I've noticed that while running the sparse test, the Watcom compiler required
- about 8M of RAM. All the other compilers produced executables that only
- required about 2M of RAM when executed, which requires further investigation.
- All of the compilers except Borland performed equally well in the sparse test.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.5. Closing Remarks ΓòÉΓòÉΓòÉ
-
- When I began this series of tests, I was hoping that there would be a clear
- "winner." However, I do not think that one exists; each of the products have
- their own unique qualities which will appeal to different users. I strongly
- feel that for people looking simply for an OS/2 C++ compiler with excellent
- tools, CSet++ is the right choice. For others, I hope the guidelines below
- will help.
-
- As a side note, I am very impressed with the EMX/GCC package. It is as good as
- any of the others and costs nothing. If I didn't need a profiler and want
- precompiled header files, I'd definetly save some cash and use it.
-
- ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
- ΓöéDesired Usage ΓöéCompiler(s) Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéInterfacing with ΓöéCSet++, Watcom C/C++ or EMX/GCC(?) Γöé
- ΓöéIOPL code Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéFloating Point ΓöéEMX/GCC, Watcom C/C++, or CSet++ Γöé
- Γöéintensive code Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéPM programming ΓöéCSet++ or Borland (because of precompiled Γöé
- Γöé Γöéheader files). Any of the 4 are quite able inΓöé
- Γöé Γöéthis area. Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéC++ code with Γöé EMX/GCC or CSet++ (Watcom follows the MSC Γöé
- Γöéworking virtual Γöéway of handling the operator=() ) Γöé
- Γöéfunctions Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéProfiler ΓöéCSet++ or Watcom C/C++ Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- ΓöéEnvironment like BC ΓöéBorland C++ for OS/2 Γöé
- Γöé3.1 Γöé Γöé
- Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
- Γöé Really fast Γöé Borland C++ or CSet++ (CSet++ is slower but Γöé
- Γöécompilation Γöéit's debugger is better) Γöé
- ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 4.5.6. Editor's Notes ΓòÉΓòÉΓòÉ
-
- After mentioning in comp.os.os2.programmer.misc that this issue would contain a
- comparison of C++ compilers, I received a request from Tim Francis in the
- C-Set++ compiler group to review the article pre-press. I gladly sent him a
- copy with the stipulation that the article would not be modified based on any
- comments he made, to which he agreed. However, I feel it necessary to put
- these comments here, as a side-note, with the intent of demonstrating the
- apparent customer-driven attitude of this group. As a disclaimer, while I do
- know some people on the compiler development team, I have never had any
- business dealings with them and am not doing this as a favor to them or because
- of any bias I have.
-
- Tim Francis writes:
-
- I didn't find anything really wrong in the compiler review. I thought C-Set++
- came out looking quite good, actually. I would be interested in seeing the
- actual code used in the execution benchmarks - we were last in the opt/full
- matrix test, and 2nd last in the opt/sparse matrix test. I'm certainly not
- trying to dispute these numbers, but our benchmarks tend to place us a little
- higher in the competition than that. Our performance evaluation guy would
- really like a look at what's happening, to see if we can improve anything.
-
- The only other comment I have is in the summary of features, Tech support
- column. As documented in the C-Set++ package, we offer the following support:
-
- o Non-defect support, and informal (best effort) defect support
-
- - Compuserve
- - Internet
- - Talklink
-
- o Formal defect support
-
- - 1-800 number, available 24hrs/day, 7 days/week.
-
- Obviously we feel that the support we offer is a key component of the product,
- so if you mention the above somewhere in EDMI I'd appreciate it.
-
- For the purposes of completeness, I am also including the following from Ian
- Ameline:
-
- If possible, could you have those floating point tests run with /Gf+ turned on
- - it will result in *much* faster FP code by relaxing our strict interpretation
- of the IEEE standard. The other compilers all use the more relaxed
- interpretation - and this places us at a bit of a performance disadvantage
- compared to them, but we do produce results that are the same as any other IEEE
- 64 bit FP processor (Of course the Intel one is uses 80 bits of precision
- naturally, and if we try to conform to the 64 bit standards, we have to
- truncate the numbers each time they're stored to a variable. This truncation
- is expensive)
-
- Also, I'll make sure the long filename bug in Extra is fixed for CSD 2.
-
- Ian's comment about the compiler's strict interpretation of IEEE standards
- prompted me to request that the author use the /Gf+ option for the optimized
- part of the benchmarks (he was using /Gf); he did so and reported that /Gf and
- /Gf+ resulted in no difference in time (it appears that /Gf invokes the default
- which is /Gf+), while /Gf- resulted in an time increase of 1.5 seconds.
-
- Select this to go to the next section
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 5. Columns ΓòÉΓòÉΓòÉ
-
- The following columns can be found in this issue:
-
- o Scratch Patch
-
-
- ΓòÉΓòÉΓòÉ 5.1. Scratch Patch ΓòÉΓòÉΓòÉ
-
- 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). This month, we have the following:
-
- o Questions and Answers
- o Snippet(s) of the Month
- o Documentation Chop Shop
- o Want Ads
-
-
- ΓòÉΓòÉΓòÉ 5.1.1. Questions and Answers ΓòÉΓòÉΓòÉ
-
- Brian Stark (stark@saturn.sdsu.edu) writes:
-
- While building entry fields I noticed the style option ES_AUTOTAB, which moves
- the cursor to the next "control window" automatically when the maximum number
- of characters are entered (Ref. OS/2 2.0 Technical Library, Programming Guide
- Volume II). My assumption is that this is done by sending a WM_CONTROL message
- to the current control windows owner. However I was unable to verify this in
- the document, or any other document. Currently I am only able to establish
- control of an entry field using the mouse, I would like to be able to use the
- arrow keys and the tab to move from field to field. Is the application
- responsible for this? If so, is there a document available that gives a clear
- description of this process, or am I just doing something wrong when I create
- the fields.
-
- After checking the toolkit header files (mainly pmwin.h) and not finding any
- notifications that would indicate what you are hoping (EN_* constants), a quick
- test application yielded that no WM_CONTROL messages are indeed sent that
- indicate the auto-tab feature has been invoked. However, the EN_KILLFOCUS and
- EN_SETFOCUS notifications are sent to the entryfield losing the focus and to
- the one receiving the focus, respectively.
-
- While these are not sent only when the auto-tab takes place (a mouse click in
- another entryfield will generate the same two notifications), a little thought
- and hocus-pocus will help you figure out how to do what you want to do.
-
- Regarding arrow keys and tabs, the system treats the keys in the following
- ways:
-
- Tab/Down arrow Moves the focus to the next control ("next" is defined
- using Z-order) with the WS_TABSTOP style.
- Backtab/Up arrow Moves the focus to the previous control ("previous" is
- defined using Z-order) with the WS_TABSTOP style.
-
- In entryfields, the left/right arrows maneuver the cursor within the control.
-
- Dominique Beauchamp (beaucham@phy.ulaval.ca) writes:
-
- What is the difference between a "string" and a "message" in a resource file?
- Each can be loaded with WinLoadString and WinLoadMessage but afterwards it
- seems we can use them the same way. If I want to program an error message box,
- should I use "string" or "message" to do it? (No, it's not obvious!)
-
- To be honest, often times I have asked the same question. Within PM, there
- seem to be a few items whose usefulness are questionable (this being one of
- them). To my knowledge, there is no difference between the two; one of the two
- might exist for historical reasons (SAA comes to mind), or there might be other
- logic at work here. In any case, I personally prefer WinLoadString since its
- name implies that it is used for more than just messages; whatever you choose,
- be consistent in your coding.
-
-
- ΓòÉΓòÉΓòÉ 5.1.2. Snippet(s) of the Month ΓòÉΓòÉΓòÉ
-
- Since I announced this new section this month, I would be expecting a lot if I
- wanted to put user-submissions here. Thus, here are some of my favorite
- subroutines:
-
- SHORT winDisplayMessage(HWND hwndParent,
- HWND hwndOwner,
- ULONG ulStyle,
- HMODULE hmDll,
- USHORT usId,
- USHORT usHelpId,...)
- //-------------------------------------------------------------------------
- // This function puts a message to the screen in PM mode (using WinMessageBox).
- // The title of the message box is assumed to have the message id usId|0x8000.
- //
- // Input: hwndParent - handle of the parent window
- // hwndOwner - handle of the owning window
- // ulStyle - specifies the WinMessageBox styles
- // hmDll - handle of the DLL containing the message
- // usId - specifies the id of the message to load
- // usHelpId - specifies the id of the corresponding help panel
- // Returns: TRUE if successful, FALSE otherwise
- //-------------------------------------------------------------------------
- {
- CHAR achMsg[1024];
- CHAR achTitle[256];
- va_list vlArgs;
- CHAR achBuf[2048];
- ULONG ulRc;
-
- if (ulStyle==0L) {
- ulStyle=MB_INFORMATION | MB_OK;
- } /* endif */
-
- if ((ulStyle & MB_SYSTEMMODAL)==0) {
- ulStyle|=MB_APPLMODAL;
- } /* endif */
-
- if (usHelpId!=0) {
- ulStyle|=MB_HELP;
- } /* endif */
-
- ulStyle|=MB_MOVEABLE;
-
- //----------------------------------------------------------------------
- // Load the message box text and title
- //----------------------------------------------------------------------
- if (WinLoadString(NULLHANDLE,
- hmDll,
- usId,
- sizeof(achMsg),
- achMsg)==0) {
- return MBID_ERROR;
- } /* endif */
-
- if (WinLoadString(NULLHANDLE,
- hmDll,
- usId | 0x8000,
- sizeof(achTitle),
- achTitle)==0) {
- return MBID_ERROR;
- } /* endif */
-
- //----------------------------------------------------------------------
- // Format the message and display it
- //----------------------------------------------------------------------
- va_start(vlArgs,usHelpId);
- vsprintf(achBuf,achMsg,vlArgs);
- va_end(vlArgs);
-
- ulRc=WinMessageBox(hwndParent,
- hwndOwner,
- achBuf,
- achTitle,
- usHelpId,
- ulStyle);
- return ulRc;
- }
-
- VOID winCenterWindow(HWND hwndCenter)
- //-------------------------------------------------------------------------
- // This function centers the window within its parent
- //
- // Input: hwndCenter - handle of the window to center
- //-------------------------------------------------------------------------
- {
- SWP swpCenter;
- RECTL rclParent;
-
- WinQueryWindowPos(hwndCenter,&swpCenter);
- WinQueryWindowRect(WinQueryWindow(hwndCenter,QW_PARENT),&rclParent);
-
- swpCenter.x=(rclParent.xRight-swpCenter.cx)/2;
- swpCenter.y=(rclParent.yTop-swpCenter.cy)/2;
-
- WinSetWindowPos(hwndCenter,NULLHANDLE,swpCenter.x,swpCenter.y,0,0,SWP_MOVE);
- }
-
-
- ΓòÉΓòÉΓòÉ 5.1.3. Documentation Chop Shop ΓòÉΓòÉΓòÉ
-
- Problem with BN_PAINT
-
- I have a confession to make: I have yet to upgrade my machine at work to OS/2
- 2.1, so the following problem might have been fixed in 2.1. I will try to
- remember to check at home, but if anyone else knows the answer already I would
- appreciate email. The problem is with buttons created with the style
- BS_USERBUTTON; the documentation states that, when the button needs to be
- repainted, you will receive a BN_PAINT notification and mpParm2 will point to a
- USERBUTTON structure which contains four fields:
-
- hwnd handle of the button window
- hps presentation space in which drawing should be performed
- fsState the current state of the button
- fsStateOld the previous state of the button
-
- According to the documentation, the fields fsState and fsStateOld can be one of
- three values - BDS_DEFAULT, BDS_HILITED, or BDS_DISABLED. When creating a
- 32-bit application utilizing "ownerdraw" buttons, this did not seem to work, so
- I added a few calls to fprintf() and below is what I got (the labelling of the
- events were added later):
-
- Upon window creation
- --------------------
- Button state = 0x00000000
- Button state (old) = 0x00040010
-
- First down
- ----------
- Button state = 0x00000100
- Button state (old) = 0xD0DF032B
-
- First up
- --------
- Button state = 0x01000000
- Button state (old) = 0x01000100
-
- Second down
- -----------
- Button state = 0x00000100
- Button state (old) = 0xD0DF032B
-
- Second up
- ---------
- Button state = 0x01000000
- Button state (old) = 0x01000100
-
- If you will accept the notion that my code is correct, you can see that the
- documentation appears to be completely wrong. I tried to reinterpret the
- values but still I ran into problems. Several calls to printf() later, a
- pattern emerged. I quickly followed my hunch and all of my problems went away.
-
- IBM defined the USERBUTTON structure incorrectly! The fsState and fsStateOld
- fields which are defined as ULONG's should be USHORT's instead. That
- simplified the problem to having to undefine BDS_DEFAULT (0x0400) and
- redefining it as 0x0000.
-
- Workaround
-
- The workaround should be obvious - either change your toolkit header files or
- define your own structure and redefine the BDS_DEFAULT constant. The former is
- preferred since you will not have to "kludge" every program that utilizes
- user-buttons to get this to work.
-
-
- ΓòÉΓòÉΓòÉ 5.1.4. Want Ads ΓòÉΓòÉΓòÉ
-
- My apologies for all of you who have sent requests for other topics that I did
- not place below. My memory is getting fragile in my old age. (*grin*) These
- seem to be good topics to write on; I have tried to assign some weighting on
- the "hotness" ("heat" just doesn't convey the idea properly, so I made up a new
- word) of the topic, so feel free to write on the really hot ones.
-
- Anything on Rexx/2 (hot) - many people have requested more articles on Rexx/2.
- I, for one, would like to see how to write external functions encased in DLL's,
- but other topics include interfacing Rexx/2 with C (as in a macro language),
- writing "Enhanced Editor" macros in Rexx/2, and interfacing with the Workplace
- Shell from Rexx/2.
-
- Using Input Hooks (hot) - this is a complicated topic which is brought up
- frequently in the comp.os.os2.programmer.misc newsgroup.
-
- Hit testing (warm) - one reader noted that the Jigsaw sample in both the IBM
- and Borland toolkits (are they not the same?) perform there own correlation and
- wondered why? Charles Petzold, in his OS/2 book "Programming the OS/2
- Presentation Manager" briefly describes correlation and hit-testing, but does
- not go into any detail nor does it describe the Gpi functions used for this
- purpose.
-
- Animation (warm) - a few readers expressed an interest in the various animation
- techniques that can be applied to PM applications. The ultimate article, in my
- opinion, would be one that develops a sprite library a la the Commodore 64's
- (and Amiga's?) built-in routines, since this is probably the hardest component
- of any good animation sequence.
-
- Client/Server (warm) - using either named pipes (with or without a network) or
- sockets, client/server programming is all-the-rage these days. Some time ago,
- I started development on a post-office and a named-pipe implementation of FTP;
- maybe I will get time to finish them and will write articles on them.
-
- Multiple Threads in a PM application (warm) - this is another complicated topic
- which is brought up from time to time in the comp.os.os2.programmer.misc
- newsgroup. While various solutions to the dilemma of communication without
- global variables have been discussed, it would be nice to see (one or more of)
- them in a more permanent place than a news server.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 6. Future Attractions ΓòÉΓòÉΓòÉ
-
- As always, 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 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 the last day of the month; any articles received after that
- time may be pushed to the next issue.
-
- The editor's can be reached at the following email addresses:
-
- o Steve Luzynski - sal8@po.cwru.edu (Internet), 72677,2140 (Compuserve).
- o Larry Salomon - os2man@panix.com (Internet).
-
- Since Steve is incapacitated at the moment, Larry is the preferred contact at
- this time.
-
- Select this to go to the next section
-
-
- ΓòÉΓòÉΓòÉ 7. Contributors to this Issue ΓòÉΓòÉΓòÉ
-
- The following people contributed to this issue in one form or another (in
- alphabetical order):
-
- o Andre Asselin
- o Larry Salomon, Jr.
- o Gordon Zeglinski
- o Network distributors
-
-
- ΓòÉΓòÉΓòÉ 7.1. Andre Asselin ΓòÉΓòÉΓòÉ
-
- Andre Asselin recently graduated Cum Laude from Rensselaer Polytechnic
- Institute with a Bachelor of Science degree in Computer Science. He has worked
- with OS/2 since version 1.3, and also has extensive experience with MS-DOS and
- Microsoft Windows. He currently works in IBM's OS/2 TCP/IP Development group
- in Raleigh NC, where his responsibilities include the NFS client, a remote file
- system implemented as an IFS.
-
- Andre is also a member of Alpha Sigma Phi Fraternity, and enjoys hockey,
- soccer, and a good science fiction novel. He can be reached via email at
- asselin@vnet.ibm.com or on CompuServe at 71075,133.
-
-
- ΓòÉΓòÉΓòÉ 7.2. Larry Salomon, Jr. ΓòÉΓòÉΓòÉ
-
- Larry Salomon 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 included with the IBM Professional Developers Kit CD-ROM currently
- being distributed by IBM. Currently, he works for International Masters
- Publishers in Stamford, Connecticut and resides in Bellerose, New York with his
- wife Lisa.
-
- Larry can be reached electronically via the Internet at os2man@panix.com.
-
-
- ΓòÉΓòÉΓòÉ 7.3. 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 and is soon to enter 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.
-
-
- ΓòÉΓòÉΓòÉ 7.4. Network distributors ΓòÉΓòÉΓòÉ
-
- These people are part of our distribution system to provide EDM/2 on networks
- other than the Internet. Their desire to help provide others access to this
- magazine is voluntary and we appreciate them a lot!
-
- o Paul Hethman (hethman@cs.utk.edu) - Compuserve
- o David Singer (singer@almaden.ibm.com) - IBM Internal
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- Precompiled headers are very useful when including OS2.H. Precompiled header
- files can greatly decrease the amount of time necessary to compile files that
- include many and/or large header files. However, not all compilers are equal in
- this respect. Borland compiles all headers into one large file. This probably
- make it a bit faster to access than multiple files. But, when one header
- changes, all headers must be recompiled and stored in the large file. IBM's
- CSet++ on the other hand uses one precompiled file for each header. Thus, when
- you change one of your header files, only that file has to be recompiled. Also,
- the method employed by CSet++ allows the same precompiled headers to be used by
- multiple projects, unlike the method used by Borland.
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with Borland's compiler:
-
- -I.. -If:\bcos2\include -ff -G -4 -O2it -vi -c -D_USE_POST_FIX_
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with IBM's compiler:
-
- /I.. /Tdp /J- /Si- /O+ /Oi+ /Os+ /W1 /Gf /Gi /G4 /Gx+ /C /d_USE_POST_FIX_
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with Watcom's compiler:
-
- /i=.. /i=. /i=f:\watcom\H /i=f:\TOOLKIT\C\OS2H /mf /4r /bt=os2 /sg /d_USE_POST_FIX_ /oneatx /zp4
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with GNU's EMX compiler:
-
- -c -O2 -m486 -I..
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with Borland's compiler:
-
- -I.. -If:\bcos2\include -ff -G -4 -vi -c -D_USE_POST_FIX_
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with IBM's compiler:
-
- /I.. /Tdp /J- /Si- /W1 /Gf /Gi /G4 /Gx+ /C /d_USE_POST_FIX_
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with Watcom's compiler:
-
- /i=.. /i=. /i=f:\watcom\H /i=f:\TOOLKIT\C\OS2H /mf /4r /bt=os2 /sg /d_USE_POST_FIX_ /zp4
-
-
- ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
-
- The following command line options were used with GNU's EMX compiler:
-
- -c -m486 -I..
-