home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / xwplascr.zip / XWPL0208.ZIP / progref.inf (.txt) < prev    next >
OS/2 Help File  |  2002-07-02  |  83KB  |  2,051 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. XWorkplace Programmer's Guide and Reference ΓòÉΓòÉΓòÉ
  3.  
  4.      Notices 
  5.  
  6.      Introduction -- start here 
  7.  
  8.      National Language Support 
  9.  
  10.      The XWorkplace source code 
  11.  
  12.      Source code details 
  13.  
  14.      Adding features to XWorkplace 
  15.  
  16.      Miscellaneous WPS programming notes 
  17.  
  18.  
  19. ΓòÉΓòÉΓòÉ 2. Notices and Legalese ΓòÉΓòÉΓòÉ
  20.  
  21. Please see the XWorkplace User Guide for the "Notices" section: the GNU General 
  22. Public Licence (GPL), the development team, credits, and thank you's. 
  23.  
  24.  
  25. ΓòÉΓòÉΓòÉ 3. Introduction -- Start Here ΓòÉΓòÉΓòÉ
  26.  
  27. Welcome to the XWorkplace source code! 
  28.  
  29. This book has been written by XFolder's and XWorkplace's original author, 
  30. Ulrich M╨ñller, to introduce you to the world of XWorkplace programming. 
  31.  
  32. This book covers two different things: 
  33.  
  34.    1. Information about XWorkplace National Language Support (NLS). This is of 
  35.       interest for people who would like to translate XWorkplace to a new 
  36.       language. No knowledge of C programming is required for translations, but 
  37.       knowing HTML helps. 
  38.  
  39.       See "National Language Support" for more information. 
  40.  
  41.    2. Information about the XWorkplace C source code. This is mainly of 
  42.       interest for programmers who would like to contribute to XWorkplace, find 
  43.       bugs, or who are just interested in learning how the thing is 
  44.       functioning. 
  45.  
  46.       See "The XWorkplace Source Code" for a general introduction and how to 
  47.       compile. 
  48.  
  49.       See "Source Code Details" for information about specific XWorkplace 
  50.       features and their implementation. This is useful for contributors. 
  51.  
  52.       See "Adding Features to XWorkplace" for information about how to hook 
  53.       your own code into XWorkplace. 
  54.  
  55.  If you have questions, please post a message to 
  56.  xworkplace-dev@yahoogroups.com, which is the mailing list for XWorkplace 
  57.  developers. 
  58.  
  59.  But if you want to start writing WPS classes, please don't start asking things 
  60.  like "What is an IDL file?". If you have never created a WPS class, please 
  61.  read the excellent courses at EDM/2 (www.edm2.com) first, which explain a lot 
  62.  of things to get you started. As far as I know, XWorkplace is the most complex 
  63.  WPS source code available, and it probably does not serve very well as a WPS 
  64.  beginner's tutorial. 
  65.  
  66.  Thanks! 
  67.  
  68.  
  69. ΓòÉΓòÉΓòÉ 4. National Language Support (NLS) ΓòÉΓòÉΓòÉ
  70.  
  71.      Overview 
  72.      Requirements for translations 
  73.      Preparations 
  74.      The main NLS DLL (XFLDRxxx.DLL) 
  75.      The INF and HLP files 
  76.      The h2i utility 
  77.      Images and screenshots 
  78.      Other files 
  79.      Testing your NLS files 
  80.  
  81.  
  82. ΓòÉΓòÉΓòÉ 4.1. Overview ΓòÉΓòÉΓòÉ
  83.  
  84. National Language Support (NLS) is done by separating everything that is 
  85. language-dependent from the actual program logic. The way XWorkplace does this 
  86. is that all the NLS stuff is packaged into files that are completely separate 
  87. from XFLDR.DLL so you can change XWorkplace's language without having to 
  88. recompile XWorkplace itself. 
  89.  
  90. XWorkplace NLS packages identify themselves to the XWorkplace core via country 
  91. codes, as described on the "COUNTRY" page in the OS/2 Command Reference 
  92. (CMDREF.INF). 
  93.  
  94. XWorkplace's language depends on exactly one setting in OS2.INI (application 
  95. "XWorkplace", key "LanguageCode"). If that setting is changed, XWorkplace 
  96. assumes a whole new set of language files to be present. The setting is only 
  97. checked once at WPS startup or later if you explicitly load a new language in 
  98. the XWorkplace Setup object. If no code is present, "001" for US English is 
  99. assumed. 
  100.  
  101. The XWorkplace sources contain everything for creating the US English NLS 
  102. package, as it comes with the standard XWorkplace binary release. The language 
  103. code for US English is "001". Everything that is related to English NLS is 
  104. therefore in the 001\ directory tree. 
  105.  
  106. The first step you'll have to take is finding out your country code. For 
  107. example, Italian would be 039. 
  108.  
  109. Unfortunately, XWorkplace's National Language Support (NLS) is spread across 
  110. quite a number of files, which have different file formats. 
  111.  
  112. Basically, XWorkplace's NLS can be separated into three parts: 
  113.  
  114.    1. Run-time NLS: this is all the language-dependent things that XWorkplace 
  115.       will ever display to the user, such as menus, dialogs, messages, and 
  116.       notebook pages. 
  117.  
  118.       Here we have: 
  119.  
  120.           The NLS DLL to be put into the XWorkplace bin subdirectory. This 
  121.            file contains all language-dependent Presentation Manager (PM) 
  122.            resources, mostly dialogs and menus. Also, a lot of strings are 
  123.            stored here. 
  124.  
  125.            The NLS DLL is called xfldrXXX.dll, with "xxx" being your 
  126.            three-digit language code. The files neccessary to translate this 
  127.            DLL are in the 001\dll directory. All this goes into 
  128.            bin\xfldr001.dll in the binary release. 
  129.  
  130.            See "The main NLS DLL" for details. 
  131.  
  132.           The XWorkplace message file, help\xfldrXXX.tmf. This file holds all 
  133.            kinds of messages which are mostly displayed in XWorkplace's message 
  134.            boxes and are too large to be put into the resources of the NLS DLL 
  135.            (because PM string resources are limited to 256 characters, 
  136.            unfortunately). 
  137.  
  138.            The file has a format similar to that of the source files for the 
  139.            IBM MKMSGF.EXE utility, but using that utility is not necessary for 
  140.            XWorkplace. There are several *.tmf files in the 001\misc directory 
  141.            in the sources, which are combined to form help\xfldr001.tmf in the 
  142.            binary release. 
  143.  
  144.            See "Other files" for details. 
  145.  
  146.           The WPS class descriptions which are displayed on the "WPS Classes" 
  147.            settings page in the "Workplace Shell" object. This was introduced 
  148.            with XFolder 0.80 also. 
  149.  
  150.            This file is called XFCLSxxx.TXT, with "xxx" being your three-digit 
  151.            language code. It also resides in the 001\misc directory. 
  152.  
  153.            See "Other files" for details. 
  154.  
  155.           A number of REXX .CMD and text files for XWorkplace's installation. 
  156.            The files to be translated are in the 001\misc subdirectory and go 
  157.            into install\ in the binary release. 
  158.  
  159.            See "Other files" for details. 
  160.  
  161.  
  162.    2. Documentation: the XWorkplace User Guide (INF file) and online help (HLP 
  163.       file). This is not absolutely necessary and probably the larger part of 
  164.       the translation work, since I have written so much text over time. 
  165.  
  166.       Here we have: 
  167.  
  168.           The XWorkplace Online Reference (INF) in the XWorkplace main 
  169.            directory. 
  170.  
  171.            This file is called xfldrXXX.inf, with "xxx" being your three-digit 
  172.            language code. The HTML source files neccessary to translate this 
  173.            file are in the 001/inf.001 subdirectory. 
  174.  
  175.            See "The INF and HLP files" for details. 
  176.  
  177.           The XWorkplace HLP file in the HELP subdirectory. This file holds 
  178.            all the help panels that are displayed when you press F1. 
  179.  
  180.            This file is called xfldrXXX.hlp, with "xxx" being your three-digit 
  181.            language code. The files neccessary to translate this file are in 
  182.            the 001/xwphelp2 subdirectory. 
  183.  
  184.            See "The INF and HLP files" for details. 
  185.  
  186.            (Yes, I know the directory naming conventions might seem strange, 
  187.            but if you have ever tried to rename a directory with CVS, you will 
  188.            understand.) 
  189.  
  190.  
  191.    3. Installation: a number of files which are only used while XWorkplace is 
  192.       being installed. These set up XWorkplace objects and INI keys in a 
  193.       certain language. Please see the README in the MISC directory for 
  194.       details. 
  195.  
  196.    4. The Warp 4 SmartGuide script which was present with XFolder and 
  197.       XWorkplace before V0.9.7 is gone now. 
  198.  
  199.  
  200. ΓòÉΓòÉΓòÉ 4.2. Required Tools ΓòÉΓòÉΓòÉ
  201.  
  202. Even though all the source files in this package can be edited using any editor 
  203. (because they're all plain text files), you will need some extra utilities to 
  204. create the actual NLS files. 
  205.  
  206. In any case, a C compiler is not required. 
  207.  
  208. To be more precise: 
  209.  
  210.      I have written my own utility which converts the HTML sources for the INF 
  211.       and HLP files to IPF format for IPFC (see below). This is in the 
  212.       xwphelpers repository on Netlabs, so in addition to the XWorkplace 
  213.       sources, you will need to check out xwphelpers as well. The utility is 
  214.       called h2i.exe and gets called automatically by the makefiles. 
  215.  
  216.      The makefiles also convert the GIF files for the INF and HLP files to BMP 
  217.       format automatically. For this to work, you will need the "Generalized 
  218.       Bitmap Module" (GBM) package from Hobbes. The makefiles assume that 
  219.       gbmsize.exe is on your PATH. 
  220.  
  221.      In order to create INF and HLP files, you need IBM's "Information 
  222.       Presentation Facility Compiler" (IPFC.EXE). This thing is part of the 
  223.       OS/2 Developer's Toolkit, which is finally included with eComStation and 
  224.       the IBM Convenience Packs. 
  225.  
  226.       If you don't have the Toolkit, IPFC is contained in the Device Driver 
  227.       Development Kit (DDK), which IBM has put online at 
  228.       http://service.boulder.ibm.com/dl/ddk/priv/ddk-d. You will need to 
  229.       register, but then downloads are free. Download combase.zip, which has 
  230.       IPFC plus a number of other tools. (Note: I was reportes that apparently 
  231.       this is now in tools.zip.) After unpacking, IPFC is in the DDK\base\tools 
  232.       directory, which you should include in your PATH. 
  233.  
  234.      The makefiles in this package were written for IBM NMAKE, which comes 
  235.       with all the IBM compilers (and also with the DDK mentioned above). I'm 
  236.       not sure these will work with other MAKE utilities, such as DMAKE or GNU 
  237.       make. I'd be grateful for feedback. 
  238.  
  239.       The makefiles are only for conveniently updating the target NLS files. If 
  240.       you don't have NMAKE, you can still assemble the files manually. See the 
  241.       following pages for details. 
  242.  
  243.      XWorkplace V0.9.0 and above can read the TMF message file directly, so 
  244.       MKMSGF.EXE is no longer needed to compile message files. 
  245.  
  246.  
  247. ΓòÉΓòÉΓòÉ 4.3. Preparations ΓòÉΓòÉΓòÉ
  248.  
  249. XWorkplace strictly separates language-dependent resources from the rest of the 
  250. program. To make things easier, all language-dependent resources are in the 
  251. "001" subtree of the main XWorkplace directory, which holds all English NLS 
  252. files. 
  253. Here's a list of things you need to do before you can begin translations. 
  254.  
  255.    1. The first thing you need to do is find out your three-digit language 
  256.       code. Open the OS/2 Command Reference, "Country" page, and find the code 
  257.       for your country. 
  258.  
  259.    2. Make a copy of the entire 001 directory tree within the XWorkplace source 
  260.       tree, renaming it to your country code. For example, if your language is 
  261.       Italian, you should have a 039 tree next to the 001 tree. 
  262.  
  263.    3. Some files in the 001 directory carry a three-digit language code in 
  264.       their respective names. For your language, you need to change all the 
  265.       filenames with "001" in their names to your country code (e.g. 039 for 
  266.       Italian). For example, rename dll\xfldr001.dlg to dll\xfldr039.dlg. 
  267.  
  268.    4. You will also have to change the dll\*.def file and dll\makefile, which 
  269.       assume a country code of 001 at this point. Required changes are noted in 
  270.       the files themselves. 
  271.  
  272.    5. Open dll\xfldrXXX.rc (with "xxx" being your country code) and find the 
  273.       strings "ID_XSSI_DLLLANGUAGE" and "ID_XSSI_NLS_AUTHOR". Change those two 
  274.       to match your language and name; this is the information that is 
  275.       displayed to the user in the "Language" drop-down box in the "XWorkplace 
  276.       Setup" settings object. 
  277.  
  278.  You should now be ready to recompile the NLS DLL for the first time. 
  279.  
  280.  If you have IBM VAC++, you can simply use MAKE.CMD to have the DLL recreated. 
  281.  Open MAKE.CMD and check somewhere in the middle where the script checks for 
  282.  the presence of the 049 directory, and change the variables to point to your 
  283.  new directory instead. Running MAKE.CMD should then work fine, since all the 
  284.  neccessary files are included. 
  285.  
  286.  Otherwise, things get a bit more complicated. Since the resource compiler 
  287.  (RC.EXE) is already included with every OS/2 installation, you can try the 
  288.  following: 
  289.  
  290.    1. Copy an existing XWorkplace resource DLL (e.g. xfldr001.dll) into your 
  291.       new NLS directory; rename it so that it contains your language code (e.g. 
  292.       xfldr039.dll). 
  293.  
  294.    2. Open a command line in that directory. 
  295.  
  296.    3. Type rc xfldr039.rc xfldr039.dll (replace "039" with your language code), 
  297.       which should create a new .RES file and link it against the existing DLL. 
  298.  
  299.  After recompiling, you can test the DLL as described in "Testing the DLL". 
  300.  
  301.  
  302. ΓòÉΓòÉΓòÉ 4.4. The NLS DLL ΓòÉΓòÉΓòÉ
  303.  
  304. Files that need to be changed: 
  305.  
  306.      xfldr001.def: The module definition file. Required changes are noted in 
  307.       the file itself. 
  308.  
  309.      makefile: Makefile for IBM NMAKE. Required changes are noted in the file 
  310.       itself. 
  311.  
  312.      xfldr001.rc, xfldr001.dlg: These are the main resource files which need 
  313.       lots of changes. 
  314.  
  315.       I've documented everything you need to change in the .RC file. 
  316.  
  317.       The .DLG file is included when the RC files is recompiled. It contains 
  318.       all the XWorkplace dialogs (i.e. notebook pages and other dialog 
  319.       windows). Sorry, there are no comments in there because I'm using 
  320.       DLGEDIT.EXE to create the dialogs, which rewrites the DLG file at every 
  321.       change, so all comments in there get lost. 
  322.  
  323.       Note: Because of this stupid limitation, I am currently trying to get rid 
  324.       of all the dialog resources and eventually the .DLG file altogether. 
  325.       Starting with V0.9.16, more and more dialog resources are converted so 
  326.       that XWorkplace only loads the strings for the dialog elements from the 
  327.       string tables in the .RC file any more and creates the dialog dynamically 
  328.       at run time. This also saves you from realigning the controls if you 
  329.       don't have enough space. 
  330.  
  331.  For the remaining dialogs, you can use DLGEDIT.EXE, the IBM dialog editor from 
  332.  the Developer's Toolkit, to change the dialogs. (This will not affect the .RC 
  333.  file.) For this, you will need to create the .RES file first. This is done by 
  334.  MAKE.CMD; alternatively, you can start RC.EXE with the "-r" option, which 
  335.  creates a .RES instead of linking the resources to an executable. 
  336.  
  337.  If you then open the .RES file with the dialog editor, you can choose 
  338.  include/dlgids.h as an include file so that all the numerical ID's have a more 
  339.  meaningful name. 
  340.  
  341.  When you then save the file, the .RES and .DLG files will be recreated by 
  342.  DLGEDIT. The .RC file remains untouched though. 
  343.  
  344.  The dialog editor has a helpful "Translate mode" in its "Options" menu which 
  345.  disables a lot of menu items so you don't accidentally change dlg ID's or 
  346.  other important stuff. 
  347.  
  348.  I don't know if you can use the URE editor also, I have not tried that. 
  349.  
  350.  
  351. ΓòÉΓòÉΓòÉ 4.5. The INF and HLP Files ΓòÉΓòÉΓòÉ
  352.  
  353. The sources for the INF and HLP files are written using a slightly extended 
  354. HTML syntax. Creating INF and HLP files is therefore a two-step process: 
  355.  
  356.    1. The HTML sources are translated into an .IPF source file, using my the 
  357.       h2i utility. I am no longer using html2ipf.cmd because it's so damn slow 
  358.       and doesn't support string replacements. 
  359.  
  360.    2. Next, the .IPF source is fed into IBM's ipfc from the Developer's 
  361.       Toolkit. See "Requirements" for where to get this utility. 
  362.  
  363.  Please use the make.cmd file on the top level of the XWorkplace source files 
  364.  to have the doc files created. 
  365.  
  366.  I recommend translating all the .HTML files and keep using make.cmd to have 
  367.  the HTML files converted into a single .IPF file (using my h2i utility), which 
  368.  can then be fed into ipfc. This has the advantage that you'll only have to 
  369.  change some panels in future versions, of which I will keep track. Also, I 
  370.  always note changes to the INF and HLP files in the HTML source files in HTML 
  371.  comments tags, so you can easily search for what's changed. 
  372.  
  373.  The "root" file in each of the two source directories is called xfldrXXX.html, 
  374.  respectively, with "xxx" being your country code (which you should change in 
  375.  this one filename because h2i will use this name for the target IPF file 
  376.  also). 
  377.  
  378.  In any case, mind these important notes: 
  379.  
  380.      The (slightly awkward, I admit) structure of the files is the following, 
  381.       in both directories: 
  382.  
  383.       xfldrXXX.html is the "root" file. All other files are somwhere below in 
  384.       the INF/HLP table-of-contents hierarchy, depending on the SUBLINKS tags 
  385.       in the HTML source files. 
  386.  
  387.      Do not change filenames! h2i sorts the IPF pages internally 
  388.       alphabetically according to the filenames, that's why I've implemented 
  389.       these strange naming conventions. I admit that since the structure has 
  390.       developed over time, it may not seem very logical to you, but it works. 
  391.       Changing things here will result in a lot of work, since all the links in 
  392.       the HTML files would have to be adjusted also. 
  393.  
  394.      Within the HTML files, do not change anything within angle brackets 
  395.       ("<xxx>"). Translate only the text outside of these. Even though some 
  396.       tags might not be good HTML style and the HTML files might not look 
  397.       pretty when viewed with Netscape, certain tag combinations (especially 
  398.       the <BR><LI> combinations) are neccessary to make the pages look good for 
  399.       IPF. 
  400.  
  401.      Don't forget to translate the page titles (in between the <TITLE> tags). 
  402.       This is what appears in the title of a panel window and in the "Table of 
  403.       contents" tree. I've forgotten this many times... 
  404.  
  405.      I do not recommend translating everything for the INF book. For the old 
  406.       XFolder, I did the German translation myself, and I think that the 
  407.       "Revision history" section makes no sense translating, because it is 
  408.       frequently updated and NLS versions didn't exist for the older versions 
  409.       anyway. Also, the "XWorkplace Internals" pages apply to programmers, 
  410.       which need to know English anyway, because otherwise they won't find 
  411.       their way through the required Toolkit docs either. So I think you can 
  412.       save yourself some work there. 
  413.  
  414.  
  415. ΓòÉΓòÉΓòÉ 4.6. The h2i Utility ΓòÉΓòÉΓòÉ
  416.  
  417. Older versions of XFolder and XWorkplace used the very valuable html2ipf.cmd 
  418. script by Andrew Pavel Zabolotny which has served me quite well over the years. 
  419. However, this has now been replaced with my own h2i.exe utility, which is both 
  420. faster and more flexible. 
  421.  
  422. h2i is contained in the xwphelpers repository at netlabs (see "Requirements"). 
  423. Start h2i to have its syntax explained. It works quite similar to html2ipf.cmd, 
  424. so you can also check HTML2IPF.INF for the general principle. 
  425.  
  426. In addition, h2i supports the following: 
  427.  
  428.      The <HTML> tag has new attributes: XPOS= and YPOS= work just like IPF's 
  429.       "x" and "y" tags; WIDTH= and HEIGHT= are the same as in IPF. 
  430.  
  431.      The <A> tag accepts a new AUTO= attribute, which works just like HREF=, 
  432.       but automatically opens and closes the window (this is, for example, used 
  433.       on the "Introduction" page of the XWorkplace Online Reference). 
  434.  
  435.      The <CITE> and </CITE> formatting tags are now set to use a 
  436.       non-proportional font, which is used extensively. 
  437.  
  438.      Some formatting changes (<UL>, <BR>, <B> etc.). 
  439.  
  440.      As opposed to html2ipf, h2i supports the resid attribute to the <HTML> 
  441.       tag to allow setting the resid explicitly, which is very helpful for 
  442.       composing help panels that can actually get called by ID from XWorkplace. 
  443.  
  444.      In addition, h2i supports string replacements via entities. An entity 
  445.       always has the form &entity; and whatever is between the "&" and and ";" 
  446.       characters can be dynamically replaced. Since h2i can also parse C 
  447.       include files for C preprocessor #define's, this allows for including the 
  448.       same headers in XWorkplace and h2i to share definitions and resids. 
  449.  
  450.      Finally, h2i supports the new <IFDEF> and <IFNDEF> tags for conditional 
  451.       compiles. 
  452.  
  453.  
  454. ΓòÉΓòÉΓòÉ 4.7. Images and Screenshots ΓòÉΓòÉΓòÉ
  455.  
  456. The images in both the INF and HELP directory are in GIF format. Unfortunately, 
  457. HTML does not support the OS/2 BMP format, and ipfc does not support GIF. 
  458.  
  459. So the makefiles in INF and HELP automatically convert all GIF images to BMP 
  460. format, if required. This requires gbmsize.exe to be on your PATH (see 
  461. "Requirements") 
  462.  
  463. If you do not want to use gbmsize, you can convert all the GIFs to BMPs 
  464. manually, e.g. using PMView. Be careful though: IPFC only supports uncompressed 
  465. OS/2 1.3 bitmaps. That is, neither compressed bitmaps nor Windows or OS/2 2.0 
  466. bitmaps work. This is annoying, because IPFC's own image compression is totally 
  467. outdated, but there's nothing we can do about this. 
  468.  
  469. I'd be very grateful if you could create your own screenshots for the online 
  470. documentation to reflect your language. 
  471.  
  472. I have used the following settings for the screenshots (just for your 
  473. information, you don't have to use these): 
  474.  
  475. Fonts used:
  476. Titlebars: Humanist 521, 13 points (available on the
  477.            CorelDraw 4 CD in Type 1 format)
  478. All the other fonts are set to 9.WarpSans.
  479. CandyBarZ installed, colors:
  480. Active:     top 191/0/0, bottom 52/0/0
  481. Inactive:   top 160/160/130, bottom 40/40/40
  482. Oh yes, XWorkplace installed. ;-)
  483.  
  484. Now, if you create your own screenshots, save them as GIFs with the exact 
  485. filenames of the originals (e.g. trunc.gif); you must then DELETE the 
  486. respective BMP file, because HTML2IPF will only call the image converter for 
  487. BMP if no BMP file of the same name exists. 
  488.  
  489. Tricks to reduce file sizes: 
  490.  
  491. Keep in mind that HLP/INF files have their own compression scheme which works 
  492. best when much redundant data is in the bitmap files. For those who know what 
  493. that is: IPFC compresses using a modified Lempel-Ziv-Welch algorithm (similar 
  494. to the GIF format). In plain English, large areas which have the same color can 
  495. be compressed best. 
  496.  
  497. This leads to the following recommendations: 
  498.  
  499.      Do not take screenshots of folders with background bitmaps. There will be 
  500.       practically no compression on those. 
  501.  
  502.      Use as few colors as possible. You can use PMView to reduce the number of 
  503.       colors to, say, 12 colors, which usually still looks alright. 
  504.  
  505.      When converting images, make sure you don't have "dithering" or "error 
  506.       diffusion" enabled, because this will add lots of extra pixels which will 
  507.       make compression less efficient. 
  508.  
  509.      Also, if you need to scale images to a smaller size, make sure not to 
  510.       enable any "interpolation", i.e. introducing extra pixels to make colors 
  511.       smoother. This adds lots more colors to the file, which cannot be 
  512.       compressed well either. 
  513.  
  514.  
  515. ΓòÉΓòÉΓòÉ 4.8. Directory "MISC" ΓòÉΓòÉΓòÉ
  516.  
  517. The MISC directory contains files used by XWorkplace's installation script 
  518. (INSTALL.CMD) plus the SmartGuide Script used for the XWorkplace introduction. 
  519.  
  520.      INSTxxx.MSG (with "xxx" being your country code) was used for 
  521.       installation messages before the WarpIN installer was used. Even though 
  522.       the old INSTALL.CMD still works for XWorkplace, it really doesn't make 
  523.       much sense to translate this message file any more. 
  524.  
  525.       The file was used by XHELP.CMD (in the XWorkplace package, taken from my 
  526.       CommandPak), which is capable of extracting single text messages in 
  527.       between the <TOPIC>; and </TOPIC> tags in this file. The text between 
  528.       these tags is then displayed on the screen. 
  529.  
  530.       If you still wish to translate this file, what you need to do here is 
  531.       simply translate all the text which follows a <TOPIC> tag. The text is 
  532.       displayed "as is", and no formatting is performed; as a result, you must 
  533.       take care that no more than 80 characters are contained in a line. 
  534.  
  535.       You also should take care of the line breaks: it makes a difference in 
  536.       output whether a </TOPIC> end tag is found at the end of a line or at the 
  537.       beginning of a new line, because in the latter case, the line break is 
  538.       still printed to the screen. 
  539.  
  540.       Just one more note: Do not change the keys mentioned in this file ("X", 
  541.       "Y", "N"), even if your language does not use "Y" for saying "Yes". 
  542.       Unfortunately, INSTALL.CMD relies on these keys. :-( 
  543.  
  544.      INSTLxxx.CMD is a straightforward REXX script which creates the default 
  545.       XWorkplace installation objects (the "XWorkplace" folder plus all the new 
  546.       settings objects). Even if you don't know REXX, don't worry: you only 
  547.       have to change the strings on top of the file, which contain all the 
  548.       language-dependent things. Be careful with the quotes. Do not change 
  549.       anything else, because XWorkplace relies on it. 
  550.  
  551.       Even though XWorkplace uses WarpIN for installation, this REXX script 
  552.       gets called after the first WPS restart after installation. 
  553.  
  554.      Similarly, CROBJxxx.CMD creates the default XWorkplace Configuration 
  555.       Folder. 
  556.  
  557.       This REXX script gets called by INSTLxxx.CMD. Also, this gets called 
  558.       independently when the "Recreate config folder" button is pressed on the 
  559.       "Objects" page in the "XWorkplace Setup" object. 
  560.  
  561.      SOUNDxxx.CMD is the REXX script which creates the neccessary INI entries 
  562.       for having the new XWorkplace system sounds in your "Sound" object. Only 
  563.       change the strings at the top of the file to your language. 
  564.  
  565.       This REXX script gets called from the "Features" page in the "XWorkplace 
  566.       Setup" object when extended system sounds are enabled. 
  567.  
  568.      XFLDRxxx.SGS used to be a Warp 4 SmartGuide script to display the 
  569.       "Welcome" window after XWorkplace has been installed and the WPS has been 
  570.       restarted. This is no longer distributed starting XWorkplace V0.9.7, 
  571.       since SmartGuide is no longer supported with OS/2. Do not translate it. 
  572.  
  573.  
  574. ΓòÉΓòÉΓòÉ 4.9. Testing Your NLS Files ΓòÉΓòÉΓòÉ
  575.  
  576. XWorkplace's NLS depends entirely on a single entry in OS2.INI 
  577. ("XFolder"::"LanguageCode"). This entry defaults to a "001" string and can be 
  578. changed either at installation time (if the install script does it) or by using 
  579. the "Language" setting in the "XWorkplace Setup" object. 
  580.  
  581. All NLS resources are loaded depending on this one setting. That is, if you 
  582. change the language, XWorkplace expects not only your NLS DLL to be present in 
  583. /BIN, but also the TMF, HLP, and WPS class description files in /HELP. So if 
  584. you have not translated these yet, you might want to create a copy of the 
  585. English ones with your language code in the filename. 
  586.  
  587. To test a new version of your NLS files: 
  588.  
  589.      Make sure you do not currently have your new NLS DLL selected on the 
  590.       "XWorkplace Internals" settings page, because if you do, the DLL is 
  591.       locked by XWorkplace and cannot be replaced. 
  592.  
  593.       Select "US English" instead, which will unlock the previously used DLL, 
  594.       which can then be deleted from the XWorkplace directory. 
  595.  
  596.       Then put your new DLL into the BIN subdirectory and open the settings 
  597.       again; select your DLL and see if things work. 
  598.  
  599.      Additional caveat for INF/HLP files: Before compiling the .IPF to the 
  600.       .HLP/.INF files, you should make sure that the target file is not 
  601.       currently in use. 
  602.  
  603.       With INF files, that's easy: simply close it if it's open. 
  604.  
  605.       With HLP files, you have to keep in mind that the WPS keeps these files 
  606.       locked even after you've closed a help panel window. However, the WPS 
  607.       only ever keeps a single HLP file locked at a time, so in order to unlock 
  608.       the XWorkplace HLP file, simply open a default WPS help panel, e.g. by 
  609.       selecting "Extended Help" for the Desktop window. 
  610.  
  611.       You can then copy the new XWorkplace .HLP file to the XWorkplace HELP 
  612.       directory. (MAKE.CMD will do this automatically.) 
  613.  
  614.  
  615. ΓòÉΓòÉΓòÉ 5. The XWorkplace Source Code ΓòÉΓòÉΓòÉ
  616.  
  617.      Overview 
  618.      Requirements for compiling 
  619.      Build setup 
  620.      Making (building) XWorkplace 
  621.      The config.in file 
  622.      XWorkplace makefiles 
  623.      Troubleshooting 
  624.      Creating the code documentation 
  625.      The SRC\CLASSES\ directory 
  626.      The SRC\HELPERS\ directory 
  627.      XWorkplace function prefixes 
  628.      Debugging XWorkplace 
  629.  
  630.  
  631. ΓòÉΓòÉΓòÉ 5.1. Overview ΓòÉΓòÉΓòÉ
  632.  
  633. Before going into the details of source code, which is complex enough to get 
  634. even the more experienced programmer confused, please read the chapters in the 
  635. "XWorkplace internals" chapter of the XWorkplace Online reference for a first 
  636. introduction to XWorkplace's basic inner workings. 
  637.  
  638. This will give you a vague idea of what XWorkplace is doing where and deals 
  639. with the most important concepts only, so you don't get overwhelmed by all the 
  640. details which come in this file. 
  641.  
  642. The different subdirectories contain the different parts of XWorkplace. The 
  643. layout of the subdirectories has been changed with XWorkplace V0.9.0 to allow 
  644. for easier addition of new features by people other than me. Also, since 
  645. XWorkplace will be on the Netlabs CVS server, many changes had to be made to 
  646. the makefiles and code layout. 
  647.  
  648.      The 001\ directory tree still contains all the National Language Support 
  649.       (NLS) for English. 
  650.  
  651.      The BIN\ directory tree contains binary object files which are created 
  652.       from the sources (below) by the various makefiles. If that directory 
  653.       doesn't exist (it's not part of the CVS tree, for many reasons), it will 
  654.       be created automatically by the makefiles. 
  655.  
  656.       The directory structure and the makefiles are designed to not depend on 
  657.       the BIN directory tree. As a result, you can always delete the entire BIN 
  658.       directory or any single files in there to enforce a complete or partial 
  659.       recompilation by the makefiles. 
  660.  
  661.      The IDL\ directory contains SOM IDL source files for the various 
  662.       XWorkplace classes. The .DEF files in this directory are created 
  663.       automatically by the SOM compiler (SC.EXE), but not used in the build 
  664.       process (see below). 
  665.  
  666.       When invoked by the makefile, the SOM compiler is told to update the C 
  667.       sources in SRC\CLASSES and write the class header files (*.h, *.ih) to 
  668.       INCLUDE\CLASSES. 
  669.  
  670.       In general, all SOM code should be in the CLASSES subdirectories. Since 
  671.       several people might be working on the same classes, the code in CLASSES 
  672.       should only call implementation code in other directories of SRC, which 
  673.       should be prototyped in a corresponding subdirectory of INCLUDE. 
  674.  
  675.      The INCLUDE\ directory tree has all the headers for XWorkplace. 
  676.  
  677.       In that tree, INCLUDE\CLASSES\ has the headers which are generated by the 
  678.       SOM compiler from the IDL files in the IDL directory (above). There is no 
  679.       hand-written code in that directory. 
  680.  
  681.       INCLUDE\HELPERS\ has the headers for the files in SRC\HELPERS\ (see 
  682.       below). Note: This is now in a separate CVS archive on Netlabs, which is 
  683.       called "xwphelpers". You need to check out that archive to be able to 
  684.       compile. 
  685.  
  686.       INCLUDE\FILESYS\ has the headers for the files in SRC\FILESYS\ (see 
  687.       below). 
  688.  
  689.       INCLUDE\SHARED\ has headers for code which might be used by several parts 
  690.       of XWorkplace, developed by several people, and corresponds to 
  691.       SRC\SHARED. I guess you get the idea now. 
  692.  
  693.      The SRC\ directory tree contains the actual C/CPP source files for 
  694.       XWorkplace. 
  695.  
  696.       In that tree, SRC\CLASSES\ has the SOM code for the WPS classes which 
  697.       will be compiled into XFLDR.DLL. It is this DLL which loads the NLS DLL 
  698.       (XFLDRxxx.DLL, with xxx being a language code) at Desktop startup or when 
  699.       the language is changed using the "XWorkplace Internals" settings page. 
  700.       See this page for more. 
  701.  
  702.       The SRC\HELPERS\ subdirectory contains a lot of C files with helper 
  703.       functions which are independent of XWorkplace. That is, these can be used 
  704.       with any OS/2 VIO and/or PM program. The functions are grouped into 
  705.       categories. See this page for more. Note: This is now in a separate CVS 
  706.       archive on Netlabs, which is called "xwphelpers". You need to check out 
  707.       that archive to be able to compile. 
  708.  
  709.       The SRC\HELPERS\ dir also contains files from Dennis Bareis' PMPRINTF 
  710.       package, which is available in full from his homepage. Refer to the 
  711.       "Debugging XWorkplace" section for details. 
  712.  
  713.       The other subdirectories in SRC\ contain implementation code for 
  714.       XFLDR.DLL (called by the SOM code in SRC\CLASSES) or external programs 
  715.       which are part of XWorkplace, such as NetscapeDDE and Treesize. 
  716.  
  717.      TOOLS\ contains some tools used by the makefiles. See Making XWorkplace. 
  718.  
  719.  
  720. ΓòÉΓòÉΓòÉ 5.2. Required Tools ΓòÉΓòÉΓòÉ
  721.  
  722.    1. Compiler. With V0.80, I have switched to IBM VisualAge C++ 3.0 to develop 
  723.       XWorkplace. For VAC++ 3.0, fixpak 8 is strongly recommended, because the 
  724.       original crashes frequently with the complex SOM header files. 
  725.  
  726.       Other compilers are presently not supported. Most notably, some people 
  727.       have tried to compile using VAC 3.6.5 and ran into problems. 
  728.  
  729.    2. You need some OS/2 Developer's Toolkit for all the SOM header files and 
  730.       the SOM compiler. 
  731.  
  732.       I am still using the Warp 3 toolkit, mostly because if XWP is built using 
  733.       a newer toolkit, it will not start on Warp 3. Besides, it appears that 
  734.       the SOM compiler and nmake from the Warp 4.5 toolkit have some problems, 
  735.       according to some reports I got. 
  736.  
  737.    3. IBM NMAKE is our make utily. This comes with VAC, so no problem there. 
  738.  
  739.       As said above, newer nmake's appear to have problems with XWorkplace's 
  740.       makefiles, mostly with invoking the SOM compiler. I am using nmake 3, 
  741.       which comes with either the Warp 3 toolkit or VAC 3. 
  742.  
  743.    4. You need to check out the "xwphelpers" CVS archive from Netlabs also. 
  744.       XWorkplace uses a lot of code which is shared between WarpIN and 
  745.       XWorkplace, which has been separated into a new CVS archive. (Starting 
  746.       with V0.9.6, the WarpIN sources are no longer needed.) There's no way to 
  747.       compile without that code. 
  748.  
  749.    5. Only if you enable debugging code through XWP_DEBUG in config.in, you 
  750.       will need the full PMPRINTF package by Dennis Bareis. 
  751.  
  752.       Check the "Debugging" section for details. 
  753.  
  754.  
  755. ΓòÉΓòÉΓòÉ 5.3. Build Setup ΓòÉΓòÉΓòÉ
  756.  
  757. With V0.9.12, the build process has been reworked to make building a bit 
  758. easier. External environment variables are no longer needed, and the makefiles 
  759. now reference the tools by their full path, so there's no need to put the files 
  760. from tools\ onto your PATH any longer. 
  761.  
  762. Still, the following setup is recommended for XWorkplace to build successfully: 
  763.  
  764.    1. You will need to set your build environment in the config.in file before 
  765.       building will work. This replaces the external environment variables 
  766.       which were required before V0.9.12. 
  767.  
  768.    2. Because XFLDR.DLL is locked while the WPS is running, you should SET 
  769.       RUNWORKPLACE=[bootdrv]:\OS2\CMD.EXE in CONFIG.SYS. This will cause an 
  770.       OS/2 window to come up instead of the WPS after bootup (which is really 
  771.       helpful if something is wrong in the XWorkplace code). Type pmshell then 
  772.       to start the WPS. 
  773.  
  774.    3. Make sure you have at least 60 MB of free space in your TEMP directory. 
  775.       This is needed for precompiled headers. I strongly recommend using 
  776.       RAMFS.IFS for your TEMP directory. This dramatically speeds up things if 
  777.       you have 128 MB RAM or more. See Troubleshooting for hints about RAMFS. 
  778.  
  779.  
  780. ΓòÉΓòÉΓòÉ 5.4. Making (Building) XWorkplace ΓòÉΓòÉΓòÉ
  781.  
  782. Starting the build process. Starting with V0.9.12, this is a two-step process. 
  783. After opening a command line in the main XWorkplace directory (the parent of 
  784. src and include), do this: 
  785.  
  786.    1. Run nmake dep. This examines all source files for dependencies (#include 
  787.       statements) and writes a .depend file into each source directory which is 
  788.       then used by the makefiles to rebuild things properly. 
  789.  
  790.       Note: You only need to run nmake dep before building for the first time, 
  791.       or if source dependencies (#include statements) have changed. To be on 
  792.       the safe side, re-run nmake dep once after you have checked out new 
  793.       sources from the CVS server. 
  794.  
  795.       nmake dep uses the fantastic fastdep utility by Knut Stange Osmundsen, 
  796.       which I have stolen from the Odin sources. This should be in the root 
  797.       directory of your xwphelpers repository. 
  798.  
  799.       Note: If you have never built XWorkplace before, nmake dep will give you 
  800.       lots of warnings that headers could not be found. This is normal because 
  801.       the SOM headers for the XWorkplace classes will only be produced during 
  802.       the first full build. 
  803.  
  804.    2. After that, run either nmake all or nmake really_all to build. This will 
  805.       produce lots of object files in bin\ and the executables in bin\modules. 
  806.       At the same time, those executables are copied to the proper locations in 
  807.       your XWorkplace installation directory as specified in config.in. 
  808.  
  809.       After that, restart the WPS to have XFLDR.DLL reloaded. 
  810.  
  811.       nmake all (or just nmake) will only rebuild XFLDR.DLL, XWPDAEMN.EXE, and 
  812.       XWPHOOK.DLL , while nmake really_all will produce the full set of 
  813.       XWorkplace executables plus the NLS files. 
  814.  
  815.  Rebuilding the whole thing. To rebuild everything, you have three options: 
  816.  
  817.      Delete the entire bin\ tree. This is not part of the CVS repository at 
  818.       Netlabs and recreated dynamically for all files that have been created. 
  819.       Deleting it will cause all target object files to become outdated and 
  820.       thus be recompiled, which will then also invoke the linker. 
  821.  
  822.      Use nmake -a on the main makefile. This will even re-invoke the SOM 
  823.       compiler on all .IDL files. 
  824.  
  825.      Open and save (or touch) include/setup.h to make it newer than the target 
  826.       files. This is #include'd in all XWorkplace C files, and the makefiles' 
  827.       inference rules will then enforce recompilation of all C files. 
  828.  
  829.  
  830. ΓòÉΓòÉΓòÉ 5.5. The "config.in" File ΓòÉΓòÉΓòÉ
  831.  
  832. This section describes the build environment which is used by the makefiles. 
  833.  
  834. Before V0.9.12, these variables had to be set externally before building. This 
  835. has been changed; the environment is now set exclusively through the config.in 
  836. file in the main XWorkplace directory. 
  837.  
  838. If these values not set correctly, you'll get errors from the makefiles 
  839. (certain checks are built into those), or compilation or linking will fail. 
  840.  
  841.    1. CVS_WORK_ROOT must point to the root of your CVS working directories. The 
  842.       XWorkplace makefiles now (V0.9.6) assume that all your projects (most 
  843.       importantly, XWorkplace and XWPHelpers) are located in subdirectories of 
  844.       a single directory. (This is useful for working with CVS in the first 
  845.       place, so this shouldn't be much of a requirement.) 
  846.  
  847.       This variable must point to the parent directory of xworkplace and 
  848.       xwphelpers. The makefiles will set a number of other environment 
  849.       variables based on that variable to locate the XWorkplace and XWPhelpers 
  850.       source tree bases. 
  851.  
  852.       Example: SET CVS_WORK_ROOT=K:\cvs 
  853.  
  854.    2. TKBASE and VACBASE are new with V0.9.12 and must point to the base 
  855.       directories of your Toolkit and VisualAge C++ installations, 
  856.       respectively. Specify the parent directories of h and include. This is 
  857.       because the build process no longer relies on your INCLUDE environment 
  858.       variable, but specifies everything on the compiler and linker command 
  859.       lines. 
  860.  
  861.    3. XWPRUNNING must point to an existing XFolder/XWorkplace installation. 
  862.       Since the makefiles first create all the files in bin\, this is not 
  863.       suitable for testing your code, because XWorkplace expects a lot of files 
  864.       at fixed locations relative to the directory where XFLDR.DLL resides. 
  865.       Most makefiles will copy the target files to the directory pointed to by 
  866.       this environment variable (after unlocking executables), so after 
  867.       rebuilding, you can simply restart the WPS, and your new code will be 
  868.       running in the WPS. 
  869.  
  870.       Do one of the following: 
  871.           Install the latest XWorkplace binary WarpIN archive. Set XWPRUNNING 
  872.            to the same directory which you specified as the target path to 
  873.            WarpIN. 
  874.           Alternatively, copy the entire "release" subtree to some new 
  875.            location and specify that location with XWPRUNNING to start. 
  876.  
  877.            This must point to the parent directory of bin\, help\ etc. in the 
  878.            XFolder/XWorkplace installation tree. 
  879.  
  880.            Example: SET XWPRUNNING=J:\Tools\XWorkplace 
  881.  
  882.  
  883.    4. If XWP_DEBUG is defined (to anything), XWorkplace will be compiled and 
  884.       linked with debug code enabled. 
  885.  
  886.       This will have quite a number of consequences since this will pass the 
  887.       __DEBUG__ define to the compiler, to which many code parts react. For 
  888.       example, only if that flag is defined, PmPrintf calls will be compiled. 
  889.       See "Debugging XWorkplace" for details. 
  890.  
  891.       IMPORTANT NOTE: If you compile the debug version, you must have the 
  892.       PMPRINTF DLLs somewhere on your LIBPATH, or otherwise you'll spend days 
  893.       figuring out why XWorkplace is simply not working any more. (I had this 
  894.       once after a reinstall of OS/2, after which the DLLs where gone.) That 
  895.       is, XWorkplace classes will not load at Desktop startup, because the 
  896.       PMPRINTF DLL imports cannot be resolved. Neither will registering 
  897.       XWorkplace classes succeed. And don't expect to get an error message 
  898.       other than FALSE. 
  899.  
  900.       By contrast, if XWP_DEBUG is not defined, release code is produced. 
  901.  
  902.    5. Replacing in-use files. You can rebuild XWorkplace even while the WPS is 
  903.       up and XWorkplace is installed. The makefiles will automatically unlock 
  904.       DLLs which are currently in use (DosReplaceModule). After the rebuild, 
  905.       restart the WPS to make it use the newly built DLLs. To do this, simply 
  906.       set XWP_UNLOCK_MODULES=YES. 
  907.  
  908.       Note: This environment variable has was with V0.9.3 because with Warp 4 
  909.       FP13, unlocking WPS modules hung the WPS after the next Desktop restart. 
  910.       This problem has been fixed with FP15, so there is really no reason to 
  911.       not have this variable set to YES any more. 
  912.  
  913.       The exception to this are XWPDAEMN.EXE and XWPHOOK.DLL, which are never 
  914.       unlocked. This is intentional. Unlocking an executable which has 
  915.       registered a system hook (which becomes part of every PM process on the 
  916.       system) will never release the hook DLL again, so you'd have to reboot to 
  917.       use the new DLL. 
  918.  
  919.       Warning: If you don't restart the daemon before restarting the WPS, the 
  920.       XWorkplace startup folder will get processed again after the Desktop 
  921.       restart. To start XWPDAEMON.EXE explicitly, give it the "-D" option, or 
  922.       it will tell only you to get lost. 
  923.  
  924.       So if you get an error during the build process which says "XWPDAEMN.EXE 
  925.       is in use", kill XWPDAEMON.EXE using some process killer, which will 
  926.       properly unload the hooks, and try building again. 
  927.  
  928.  
  929. ΓòÉΓòÉΓòÉ 5.6. XWorkplace Makefiles ΓòÉΓòÉΓòÉ
  930.  
  931. The XWorkplace makefiles are quite smart, but therefore quite complex. This 
  932. section is supposed to explain why I chose this approach and what the makefiles 
  933. do exactly. 
  934.  
  935. I redesigned the entire XWP sources structure with V0.9.0 and made some more 
  936. changes with V0.9.12. The sources were supposed to be structured so that the 
  937. following was possible: 
  938.  
  939.      Several developers must be able to cooperatively work on the sources. As 
  940.       a result, it must be possible for each developer to work on his own 
  941.       directory to avoid conflicts. 
  942.  
  943.      Still, it should be possible to build the entire thing in one snap. 
  944.  
  945.      Building the entire thing should even take place if a makefile from one 
  946.       of the subdirectories was called. 
  947.  
  948.      The makefiles should be easily adjustable in case someone wants to use a 
  949.       different compiler. 
  950.  
  951.      Clean separation of files which reside on the Netlabs CVS server from 
  952.       those which are created in the build process. 
  953.  
  954.      Since the helpers from the "xwphelpers" CVS archive are used, it must be 
  955.       possible to call the makefile in that directory, but still write the .OBJ 
  956.       files into the XWorkplace bin\ directory. 
  957.  
  958.      It should be possible to rebuild the executables (XFLDR.DLL and the .EXE 
  959.       files) and just restart the WPS for the changes to take effect. 
  960.  
  961.      With V0.9.12, I was finally getting tired of always manually updating the 
  962.       makefile dependencies if #include statements were changed in the sources. 
  963.       So nmake dep support had to be introduced. 
  964.  
  965.  As a result, I came up with the following: 
  966.  
  967.      A single configuration file which sets up all compiler and linker 
  968.       options. This is setup.in in the main directory, which is included from 
  969.       all makefiles via the nmake !include directive. 
  970.  
  971.      System-dependent configuration (directories etc.) is done via another 
  972.       file, config.in. 
  973.  
  974.      The makefiles create all output files (.OBJ, .DLL, .EXE) in the bin\ 
  975.       directory, which is created if it doesn't exist. 
  976.  
  977.       To rebuild the entire thing, one can simply delete the entire bin\ tree. 
  978.  
  979.      If the main makefile is started, it changes to the subdirectories and 
  980.       calls nmake again with MAINMAKERUNNING=YES defined. This way the 
  981.       sub-makefile knows that it's started from the main makefile. Otherwise 
  982.       the sub-makefile calls the main makefile (which in turn calls the 
  983.       sub-makefile) so that the entire thing always gets rebuilt. 
  984.  
  985.      The sub-makefiles compile only. Linking is done by the main makefile. 
  986.       This way every executable can use shared code, such as the helpers. 
  987.  
  988.      nmake dep is supported through a new makefile in src\ which calls all 
  989.       makefiles in the subdirectories of src\ with either the "all" or the 
  990.       "dep" target. A "dep" target was then added to all the makefiles in src\ 
  991.       which invokes fastdep on all C files to produce the .depend file... which 
  992.       is in turn included in the makefiles. 
  993.  
  994.       This invokes fastdep.exe from the XWP Helpers directory, which I stole 
  995.       from the Odin sources. fastdep was written by Knut Stange Osmundsen and 
  996.       creates a .depend file in each source directory with all the includes 
  997.       which are retrieved directly from the C sources. 
  998.  
  999.  
  1000. ΓòÉΓòÉΓòÉ 5.7. Troubleshooting ΓòÉΓòÉΓòÉ
  1001.  
  1002.    1. If you get errors from the makefiles, make sure you have set up config.in 
  1003.       correctly. 
  1004.  
  1005.    2. Same thing if the compiler cannot find an include file, or the linker 
  1006.       cannot find libraries. 
  1007.  
  1008.    3. Make sure your TEMP, TMP, and TMPDIR directories are set correctly. Most 
  1009.       importantly, when using RAMFS.IFS, do not use a root directory because 
  1010.       apparently RC chokes on that. I have the following in CONFIG.SYS: 
  1011.  
  1012.             IFS=J:\common\ifs\RAMFS64.IFS
  1013.             CALL=J:\common\ifs\RAMDISK.EXE Z:
  1014.             RUN=I:\OS2\CMD.EXE /C md Z:\temp
  1015.             SET TMP=Z:\temp
  1016.             SET TEMP=Z:\temp
  1017.             SET TMPDIR=Z:\temp
  1018.  
  1019.  
  1020.  
  1021.    4. Also, you need to check out the "xwphelpers" CVS archive from Netlabs for 
  1022.       the helpers code. Make sure that this code is not outdated (I usually 
  1023.       update it together with the main XWorkplace code). 
  1024.  
  1025.       Same thing if you get unknown definitions or unresolved externals during 
  1026.       compiling/linking. This is most probably due to outdated helpers. 
  1027.  
  1028.    5. If the SOM compiler chokes on the .IDL files, you may have a problem with 
  1029.       the nmake version that is running. Several people have reported that the 
  1030.       nmake that comes with the Warp 4.5 Toolkit does not set SMINCLUDE 
  1031.       correctly from the makefiles. I am still running nmake 3, which comes 
  1032.       with the Warp 3 Toolkit and also with the IBM VAC 3 compiler. 
  1033.  
  1034.       Alternatively, look at idl\makefile and search for SMINCLUDE. Uncomment 
  1035.       the line that sets the environment variable and set the variable to the 
  1036.       proper values externally. Some people have gotten the thing to work like 
  1037.       that too. 
  1038.  
  1039.       The SOM compiler that comes with some versions of the Warp 4.5 Toolkit 
  1040.       appears to produce very strange errors also, according to some user 
  1041.       reports. I recommend using the Warp 3 Toolkit; see Required Tools. 
  1042.  
  1043.    6. If you get unresolved externals while linking the XCenter widgets, take a 
  1044.       look at src\shared\xwp.def, which exports the functions from XFLDR.DLL. 
  1045.  
  1046.    7. If you get something like "File XWPDAEMN.EXE/XWPHOOK.DLL is in use", use 
  1047.       WatchCat or some other process killer to kill XWPDAEMN.EXE, which will 
  1048.       automatically unload the hook DLL. Then, after the build, restart the 
  1049.       daemon by executing XWPDAEMN -D (to circumvent the error message box 
  1050.       which comes up otherwise). 
  1051.  
  1052.       See config.in for details. 
  1053.  
  1054.    8. If you get really strange compilation errors, VAC might have gotten 
  1055.       confused with precompiled headers. Delete all .PCH files in your TEMP 
  1056.       directory, or comment out the PRECH line in setup.in to disable 
  1057.       precompiled headers altogether. I have also found that killing 
  1058.       DDE4LOAD.EXE (the VAC background process) helps sometimes, for whatever 
  1059.       reason. 
  1060.  
  1061.    9. If you cannot install XWorkplace after the build, you have probably built 
  1062.       the debug version, but the PMPRINTF DLLs are not on your LIBPATH. Do not 
  1063.       build the debug version if you haven't downloaded PMPRINTF yet. See 
  1064.       "Debugging" for details. 
  1065.  
  1066.  
  1067. ΓòÉΓòÉΓòÉ 5.8. Creating the Code Documentation ΓòÉΓòÉΓòÉ
  1068.  
  1069. Starting with V0.9.0, you can have HTML documentation created for the whole 
  1070. XWorkplace code. This is done using my own xdoc utility, which can be found in 
  1071. the root directory of the XWorkplace Helpers. 
  1072.  
  1073. The sources for xdoc are still in the WarpIN source tree. 
  1074.  
  1075. xdoc is capable of parsing C/CPP source code and header files to some extent. 
  1076. When certain codes are found in a comment in the sources (e.g. @@), that 
  1077. comment is assumed to document some function and will be considered for HTML 
  1078. output. 
  1079.  
  1080. Call createdoc.cmd in the main directory, which will create the HTML 
  1081. documentation in a new subdirectory of the code tree HTML\. Open index.html 
  1082. then to get an index of all XWorkplace source files. 
  1083.  
  1084.  
  1085. ΓòÉΓòÉΓòÉ 5.9. The SRC\CLASSES\ directory ΓòÉΓòÉΓòÉ
  1086.  
  1087. SRC\CLASSES contains only C code which was originally generated by the SOM 
  1088. compiler from the IDL files in the IDL\ directory. Of course, that code has 
  1089. been extended so that the new classes do anything meaningful. 
  1090.  
  1091. As opposed to versions before 0.9.0, this directory contains SOM code only. The 
  1092. idea is that (except for fairly small method code) code in one of these class 
  1093. files should call some implementation function in a directory other than 
  1094. SRC\CLASSES. Only in doing so it is possible that several developers can 
  1095. implement features within the same WPS class. 
  1096.  
  1097. For example, src\classes\xfldr.c branches over to src\filesys\folder.c, which 
  1098. is the "folder implementation" code and has most of the folder features. 
  1099.  
  1100. The XWorkplace package contains many classes, but puts them all into a single 
  1101. DLL. This is possible by specifying the same target DLL in the IDL files. 
  1102. (XWorkplace's IDL files are now in the separate IDL\ directory.) One can put 
  1103. several classes into one .IDL file (which happens in xtrash.idl for example) or 
  1104. spread them across several IDL files too. 
  1105.  
  1106. Note that the .DEF files in IDL\ are not used. These files are created 
  1107. automatically by the SOM compiler, which cannot however create a single DEF 
  1108. file if you use several IDL files for the same DLL. For finally linking the 
  1109. whole main DLL, the makefiles instead use \src\shared\xwp.def, which I manually 
  1110. created from all the DEF files which were created by the SOM compiler. This 
  1111. file exports lots of mysterious SOM structures which allow the SOM kernel see 
  1112. the classes in the DLL. 
  1113.  
  1114.  
  1115. ΓòÉΓòÉΓòÉ 5.10. The SRC\HELPERS\ directory ΓòÉΓòÉΓòÉ
  1116.  
  1117. SRC\HELPERS contains lots of useful code which I have developed over time. This 
  1118. code is independent of XWorkplace and could be used with any OS/2 program. Some 
  1119. of the code is for PM programs, some can be used with text-mode programs also. 
  1120. Consider this a general OS/2 programming library. 
  1121.  
  1122. Note: XWorkplace's source code does not contain the helpers source code. 
  1123. Instead, during the build process, the XWorkplace makefiles branch over to the 
  1124. "xwphelpers" source tree, which is also on the Netlabs CVS server. You will 
  1125. need to set the HELPERS_BASE environment variable to point to the "xwphelpers" 
  1126. source tree for this to work. 
  1127.  
  1128.  In detail, we have: 
  1129.  
  1130.      animate.* contains some animation code. 
  1131.      cnrh.* Container helper functions (new with V0.9.0, partly moved from 
  1132.       winh.*). 
  1133.      comctl.* Various window procedures. 
  1134.      debug.* parses executables and SYM files for debugging information; used 
  1135.       by except.c (below). Introduced with V0.84, moved to SRC\HELPERS\ with 
  1136.       V0.9.0. 
  1137.      dosh.* Control Program helper functions. 
  1138.      eas.* contains helper functions to handle extended attributes. 
  1139.  
  1140.      except.* contains generic code for implementing powerful exception 
  1141.       handlers. This was introduced with V0.84 and has been moved to 
  1142.       SRC\HELPERS\ with V0.9.0. The code has been straightened out to be 
  1143.       independent of XWorkplace with the use of exception "plug-ins". See 
  1144.       "XWorkplace exception handling" for details. 
  1145.      gpih.* GPI (graphics) helper functions. 
  1146.      linklist.* contains helper functions to handle linked lists. 
  1147.      prfh.* is new with V0.82 and contains Profile (INI) helper functions. 
  1148.      procstat.* modified Kai Uwe Rommel's DosQProc() functions. 
  1149.      shapewin.* contains the ShapeWindows library. See the top of shapewin.c 
  1150.       for details (new with V0.85). 
  1151.      stringh.* contains helper functions to handle strings/texts 
  1152.      syssound.* has code for managing system sound data and sound schemes. 
  1153.      threads.* contains helper functions to synchronize threads. 
  1154.      tmsgfile.* has Christian Langanke's new .TMF (text message file) handling 
  1155.       to get rid of those ugly .MSG files. 
  1156.      winh.* Win (PM) helper functions. 
  1157.      wphandle.* Henk Kelder's WPS handles functions. 
  1158.  
  1159.  
  1160. ΓòÉΓòÉΓòÉ 5.11. XWorkplace Function Prefixes ΓòÉΓòÉΓòÉ
  1161.  
  1162. XWorkplace uses function prefixes to indicate in which source file a certain 
  1163. function resides. XWorkplace function prefixes are in lower case to distinguish 
  1164. them from the OS/2 API function prefixes. So if you encounter some lower-case 
  1165. function prefix, you can be pretty sure it's some function in MAIN or HELPERS 
  1166. and has been prototyped in the corresponding header file. 
  1167.  
  1168. If a function has no prefix, it's probably in the same source file and not 
  1169. prototyped in the headers. 
  1170.  
  1171. However, there are two general function prefixes which are used to indicate 
  1172. certain function types: 
  1173.  
  1174.      fnwp* is my general prefix for window procedures (the MRESULT EXPENTRY... 
  1175.       type), which may or may not be exported. 
  1176.  
  1177.      fncb is my general prototype for callback functions. Most of these are 
  1178.       callbacks for the notebook helpers in shared\notebook.c, but there are 
  1179.       some for functions in HELPERS also. See the respective function header 
  1180.       then. 
  1181.  
  1182.  Here are the other function headers and the files where their code resides: 
  1183.  
  1184.      anm*   helpers\animate.* 
  1185.      apm*   startshut\apm.* 
  1186.      arc*   startshut\archives.* 
  1187.      cfg*   config\cfgsys.* 
  1188.      cls*   config\classlst.* 
  1189.      cmn*   shared\common.* 
  1190.      cnrh*   helpers\cnrh.* 
  1191.      ctl*   helpers\comctl.* 
  1192.      dtp*   filesys\desktop.* 
  1193.      dosh*   helpers\dosh.* 
  1194.      dsk*   filesys\disk.* 
  1195.      ea*    helpers\eas.* 
  1196.      exc*   helpers\except.* 
  1197.      fdr*   filesys\folder.* or filesys\fdrhoty.* 
  1198.      fops*   filesys\fileops.* 
  1199.      fsys*   filesys\filesys.* 
  1200.      ftyp*   filesys\filetype.* 
  1201.      gpih*   helpers\gpih.* 
  1202.      hif*   config\hookintf.* 
  1203.      krn*   shared\kernel.* 
  1204.      lst*   helpers\linklist.* 
  1205.      mnu*   filesys\menus.* 
  1206.      ntb*   shared\notebook.* 
  1207.      obj*   filesys\object.* 
  1208.      prfh*   helpers\prfh.* 
  1209.      prc*   helpers\procstat.* 
  1210.      shp*   helpers\shapewin.* 
  1211.      snd*   helpers\syssound.* or filesys\sound.* 
  1212.      stb*   filesys\statbars.* 
  1213.      strh*   helpers\stringh.* 
  1214.      thr*   helpers\threads.* 
  1215.      tmf*   helpers\tmsgfile.* 
  1216.      wph*   helpers\wphandle.* 
  1217.      wpsh*   shared\wpsh.* 
  1218.      xsd*   startshut\shutdown.* 
  1219.      xthr*   filesys\xthreads.* 
  1220.  
  1221.      xwp*   newly introduced SOM instance methods in SRC\CLASSES 
  1222.      xwpcls*  newly introduced SOM class methods in SRC\CLASSES 
  1223.  
  1224.  
  1225. ΓòÉΓòÉΓòÉ 5.12. Debugging XWorkplace ΓòÉΓòÉΓòÉ
  1226.  
  1227. Debugging WPS applications can be really tiresome, because you have to restart 
  1228. the WPS for every tiny change you made to the source codes to take effect. And, 
  1229. as with any PM program, you can't just printf() stuff to the screen. Even 
  1230. worse, it's hard to use the PM debugger, because you have to start the whole 
  1231. WPS (PMSHELL.EXE) with it, since XFLDR.DLL is no standalone application. 
  1232.  
  1233. So I had to look for something else. 
  1234.  
  1235. To enable the debug build, set XWP_DEBUG in config.in. Again, mind the warnings 
  1236. given there. Of course, you will then have to cause a complete rebuild by 
  1237. deleting the bin\ directory. 
  1238.  
  1239. Enabling the debug code has a large number of consequences: 
  1240.  
  1241.    1. Since in debug mode, the __DEBUG__ define is passed on the compiler 
  1242.       command line, many other parts of the code can react to that. For 
  1243.       example, you will find a few interesting new items in the Desktop's 
  1244.       context menu, such as "Crash WPS" to test the exception handlers. 
  1245.  
  1246.    2. Depending on whether __XWPMEMDEBUG__ is uncommented at the bottom of 
  1247.       include\setup.h, all memory management functions will be replaced by 
  1248.       debug versions which give you very detailed logs of all memory that was 
  1249.       ever allocated. See memdebug.c in the helpers for details. This will also 
  1250.       produce an additional Desktop context menu item which will open a PM 
  1251.       window with lots of information. 
  1252.  
  1253.    3. There are a large number of _Pmpf(("xxx")) calls in the code. These are 
  1254.       for the magnificent PMPRINTF package by Dennis Bareis. 
  1255.  
  1256.       Some files from the PMPRINTF package are included so that you can 
  1257.       compile. The PM interface which actually displays the messages plus the 
  1258.       required DLLs which must be on the LIBPATH are not however. Last time I 
  1259.       checked (March 13, 2001), this package was available at 
  1260.       http://www.labyrinth.net.au/~dbareis/zips_fw/pmf96179.zip. 
  1261.  
  1262.       These calls only display anything if the proper DEBUG_xxx #define's are 
  1263.       set in include\setup.h (changed with V0.9.0). You can conditionally 
  1264.       enable groups of debugging flags in there, but some of them haven't been 
  1265.       tested in a long while and might cause compilation errors. 
  1266.  
  1267.       For the release version of XWorkplace, all these flags have been 
  1268.       disabled, so no additional code is produced at all. You thus don't have 
  1269.       to remove the commands to speed up XWorkplace, because this wouldn't make 
  1270.       any difference. 
  1271.  
  1272.       _Pmpf(("xxx")) uses regular printf syntax, except for those strange 
  1273.       double brackets, which are needed because macros don't accept variable 
  1274.       parameter lists otherwise. 
  1275.  
  1276.  
  1277. ΓòÉΓòÉΓòÉ 6. Source Code Details ΓòÉΓòÉΓòÉ
  1278.  
  1279.      XWorkplace settings 
  1280.      Folder window subclassing 
  1281.      Menu manipulation 
  1282.      Extended sort functions 
  1283.      XWorkplace threads 
  1284.      Playing sounds 
  1285.      XShutdown 
  1286.      XWorkplace exception handling 
  1287.  
  1288.  
  1289. ΓòÉΓòÉΓòÉ 6.1. XWorkplace Settings ΓòÉΓòÉΓòÉ
  1290.  
  1291. XWorkplace uses two kinds of settings: global and instance settings. 
  1292.  
  1293. The global settings are set both in the "Workplace Shell" object and on the 
  1294. "XDesktop" notebook page and are stored in the "XWorkplace" app in OS2.INI. All 
  1295. the global notebook logic is in src\shared\notebook.c. 
  1296.  
  1297. Note that the large structure called GLOBALSETTINGS that was used from XFolder 
  1298. 0.1 until XWorkplace 0.9.16 is gone now. Yes, it almost broke my heart, but I 
  1299. got sick of it. Instead, global settings are implemented via cmnQuerySetting 
  1300. and cmnSetSetting in src\shared\common.c now. 
  1301.  
  1302. By contrast, the individual object settings are stored in instance data, which 
  1303. is declared in the .IDL files. Most of these are stored and retrieved using the 
  1304. normal WPS mechanism (wpSaveDeferred/wpRestoreData) and can have a certain 
  1305. "transparent" value, which means that the global setting is to be used instead. 
  1306.  
  1307.  
  1308. ΓòÉΓòÉΓòÉ 6.2. Subclassing Folder Windows ΓòÉΓòÉΓòÉ
  1309.  
  1310. XWorkplace subclasses all WPFolder frame windows to intercept a large number of 
  1311. messages. This is needed for the majority of XWorkplace's features, which are 
  1312. not directly SOM/WPS-related, but are rather straight PM programming. 
  1313.  
  1314. For an introduction to how this works, see the top of src\folder\fdrsubclass.c. 
  1315.  
  1316.  
  1317. ΓòÉΓòÉΓòÉ 6.3. Menu Manipulation ΓòÉΓòÉΓòÉ
  1318.  
  1319. This is perhaps the most complex part of XWorkplace. After all, this is what 
  1320. I've started with, so some code parts may well be unchanged since December '97, 
  1321. when I neither knew much about C nor about WPS programming. 
  1322.  
  1323. With V0.81, all the logic for manipulating and evaluating context menus has 
  1324. been moved to a new file, menus.c. All these functions have been given the mnu* 
  1325. prefix to make this a bit clearer. 
  1326.  
  1327. The XWorkplace classes override wpModifyPopupMenu and wpMenuItem[Help]Selected 
  1328. for almost every replacement class. These overrides either handle the new 
  1329. context menu items in that method code or, for XFolder and XFldDisk, call the 
  1330. functions in menus.c, because these two classes share many common menu items, 
  1331. so we can share most of the code also. 
  1332.  
  1333. All newly inserted menu items use variable menu IDs. You can tell this from 
  1334. their #define names, which have an _OFS_ in their name (check dlgids.h). To all 
  1335. these values, XWorkplace adds the offset that is specified on the "Paranoia" 
  1336. notebook page. 
  1337.  
  1338. For an introduction to how the config folder menu items work, see the 
  1339. "XWorkplace Internals" section in the XWorkplace User Guide. XWorkplace uses a 
  1340. fairly obscure system of global variables to be able to relate menu items to 
  1341. their intended functions. All the variable menu items are stored in a global 
  1342. linked list when the context menu is opened for a folder. In each list item, 
  1343. XWorkplace also stores what kind of object (template, program object, folder 
  1344. content item etc.) the menu item represents. This list is then examined by 
  1345. wpMenuItemSelected to perform the corresponding action (create a new object, 
  1346. start program etc.). After that, the list is destroyed, so it only eats up 
  1347. memory while the context menu is open. All this code is now (V0.81) in menus.c. 
  1348.  
  1349. As opposed to the "regular" new menu items, the folder content menus are 
  1350. initially only inserted as empty submenu stubs. They are only filled with items 
  1351. when they're opened: XWorkplace intercepts WM_INITMENU in the subclassed folder 
  1352. frame proc (fnwpSubclassedFolderFrame, src\filesys\folder.c) and then populates 
  1353. the menu. These menu items are stored in the global list too and marked as 
  1354. folder content menu items so that wpMenuItemSelected will then simply open the 
  1355. corresponding Desktop object. The folder content code has now been moved to 
  1356. menus.c also. 
  1357.  
  1358. Painting the icons is then done using owner-draw menu items; the messages which 
  1359. are necessary for this are also intercepted in fnwpSubclassedFolderFrame and 
  1360. then call corresponding functions in menus.c. 
  1361.  
  1362. The folder content menu windows are also subclassed to be able to intercept 
  1363. right-mouse button clicks. The new window proc for this is called (suprise!) 
  1364. fnwpFolderContentMenu. 
  1365.  
  1366. The xfSelectingMenuItem method introduced in V0.80 has been removed again with 
  1367. V0.81 due to the problems with SOM multiple inheritance. 
  1368.  
  1369.  
  1370. ΓòÉΓòÉΓòÉ 6.4. Extended Sort Functions ΓòÉΓòÉΓòÉ
  1371.  
  1372. Folder sorting has been mostly rewritten with V0.9.12, and the documentation 
  1373. for this can be found in src\filesys\fdrsort.c. 
  1374.  
  1375.  
  1376. ΓòÉΓòÉΓòÉ 6.5. XWorkplace Threads ΓòÉΓòÉΓòÉ
  1377.  
  1378. XWorkplace is quite heavily multi-threaded and offloads most tasks which are 
  1379. probable to take some time to several threads which are always running in the 
  1380. background. Those threads create object windows and are thus normally blocked, 
  1381. unless there's real work to do. XWorkplace uses mutex semaphores all over the 
  1382. place to serialize access to global data structures. 
  1383.  
  1384. With V0.9.0, all the thread code has been put into a new file, called 
  1385. src\filesys\xthreads.c. 
  1386.  
  1387. All threads are created in krnInitializeXWorkplace (src\shared\kernel.c), which 
  1388. gets called from M_XFldObject::wpclsInitData, which is probably the first SOM 
  1389. method called when the WPS is initializing at startup. 
  1390.  
  1391. All threads have some fntXXXThread function, which is the main thread function 
  1392. passed to the thr* functions in /helpers/threads.c when the thread is created. 
  1393. These in turn create an object window using some fnwpXXXObject function as 
  1394. their window procedure. 
  1395.  
  1396. For each thread, we then have some krnPostXXXMsg function which posts a message 
  1397. to the corresponding object window. All messages are defined and explained in 
  1398. include\filesys\xthreads.h. 
  1399.  
  1400. The following additional threads are available: 
  1401.  
  1402.      The Worker thread is running with idle priority and does mainly 
  1403.       maintenance which is not time-critical. 
  1404.  
  1405.       For example, the Worker thread maintains the global linked list of 
  1406.       currently awake Desktop objects. XFldObject::wpObjectReady post 
  1407.       WOM_ADDAWAKEOBJECT to the Worker thread, which then adds the object to 
  1408.       that list. (This list is needed by XShutdown to store all the awake 
  1409.       Desktop objects; see the XWorkplace User Guide for details). 
  1410.  
  1411.       The Worker thread runs at "Idle" priority, unless more than 300 messages 
  1412.       have piled up in its message queue. In this case, the priority is 
  1413.       temporarily raised to "Regular" and set back if the message count goes 
  1414.       below 10 again. This can happen when opening folders with a very large 
  1415.       number of objects. 
  1416.  
  1417.      The "Speedy" thread is running at a high "Regular" priority for things 
  1418.       which won't take long but should not block the main WPS (Workplace) 
  1419.       thread. This thread creates an object window also.  For example, the new 
  1420.       system sounds are played here, and the Desktop start logo is shown. 
  1421.  
  1422.      The "File" thread is new with V0.9.0 and runs with regular priority, that 
  1423.       is, concurrently with the WPS user interface. This now does file 
  1424.       operations, such as moving objects to and emptying the trash can and 
  1425.       such. This thread will probably get more jobs in the future. 
  1426.  
  1427.  
  1428. ΓòÉΓòÉΓòÉ 6.6. Playing Sounds ΓòÉΓòÉΓòÉ
  1429.  
  1430. The new system sounds are played in the "Speedy" thread with high regular 
  1431. priority. Check fntSpeedyThread and fnwpSpeedyObject for details about how this 
  1432. is implemented using MMOS/2. 
  1433.  
  1434. Unfortunately, nowhere is documented how to access and modify the system sounds 
  1435. that appear in the "Sound" object. I have accidently discovered that this is 
  1436. actually fairly easy: these are stored in MMPM.INI in the MMOS/2 directory. 
  1437. Each sound has an index in that file, which I have declared in common.h (those 
  1438. MMSOUND_* #define's). These should be the same on every system. The INI data 
  1439. then contains a "<soundfile>#<description>#<volume>" string. 
  1440.  
  1441. Sound data manipulation has been moved into a separate file with V0.9.0: check 
  1442. /helpers/syssound.c for details. This now also supports sound scheme 
  1443. manipulation. 
  1444.  
  1445. To make sure that the actual sound playing (which requires MMPM/2) also works 
  1446. on systems where MMPM/2 is not installed, XWorkplace dynamically imports the 
  1447. functions from the MMPM/2 DLLs. See src\media\* for details. 
  1448.  
  1449.  
  1450. ΓòÉΓòÉΓòÉ 6.7. XShutdown ΓòÉΓòÉΓòÉ
  1451.  
  1452. XShutdown (i.e. the "eXtended Shutdown" and "Restart Desktop" features) resides 
  1453. entirely in the src\startshut\shutdown.c file. 
  1454.  
  1455. XShutdown starts two additional threads to close all the windows. This is 
  1456. described in detail in the "XWorkplace Internals" section of the XWorkplace 
  1457. User Guide. I have also tried to put plenty of comments into the sources. 
  1458.  
  1459.  
  1460. ΓòÉΓòÉΓòÉ 6.8. XWorkplace Exception Handling ΓòÉΓòÉΓòÉ
  1461.  
  1462. XWorkplace registers additional exception handlers in certain parts where I 
  1463. considered worth it. 
  1464.  
  1465. With "worth it" I mean the following situations: 
  1466.  
  1467.    1. Certain code parts crashed on my system and these parts seemed 
  1468.       error-prone enough to me to outweigh the performance loss of registering 
  1469.       and deregistering exception handlers. 
  1470.  
  1471.    2. Exception handlers must be registered for all additional threads. If no 
  1472.       exception handling was registered there, crashes would take the whole WPS 
  1473.       down, because the default WPS exception handler only deals with the 
  1474.       default WPS threads. 
  1475.  
  1476.    3. Exception handlers must also be registered every time mutex semaphores 
  1477.       are used. If a code part crashes while a mutex semaphore has been 
  1478.       requested by a function, all other threads waiting for that semaphore to 
  1479.       be released will be blocked forever. And I mean forever, because even 
  1480.       DosKillProcess won't be able to terminate that thread. You'd have to 
  1481.       reboot to get out of this. So the exception handler must always check for 
  1482.       whether a mutex semaphore is currently owned by the thread and, if so, 
  1483.       release it. 
  1484.  
  1485.  XWorkplace does not use the VAC++ library funcs for all this, but installs its 
  1486.  own set of quite complex exception handlers (using DosSetExceptionHandler()). 
  1487.  The code for exception handlers has been made independent of XWorkplace and 
  1488.  moved to /helpers/except.c with V0.9.0. 
  1489.  
  1490.  Also, I have created a few handy macros which automatically register and 
  1491.  deregister the XWorkplace exception handlers. This avoids the frequent problem 
  1492.  that one forgets to deregister an exception handler, which leads to really 
  1493.  awkward problems which are almost impossible to debug. Those macros are called 
  1494.  TRY_xxx and CATCH to mimic at least some C++ syntax. See the top of 
  1495.  src\helpers\except.c for detailed instructions how to use these. 
  1496.  
  1497.  The XWorkplace exception handlers are the following: 
  1498.  
  1499.      excHandlerLoud is the one that makes the loud sounds and writes the 
  1500.       XFLDTRAP.LOG file which is well-known to many XWorkplace users (grin). It 
  1501.       uses a longjmp() to get back to the function, which might then react to 
  1502.       that exception by trying to restore some safe state of the thread. See 
  1503.       the func header for details about how this works. 
  1504.  
  1505.       This handler is used by all the additional XWorkplace threads and also by 
  1506.       the subclassed folder frame and folder content menu window procs. This 
  1507.       slows down the system a bit because the handler must be registered and 
  1508.       deregistered for each message that comes in, but there's no other way to 
  1509.       do this. (I think.) 
  1510.  
  1511.       With V0.84, I have added lots of debugging code which I found in the 
  1512.       EXCEPTQ.ZIP package at Hobbes. The exception handlers are now capable of 
  1513.       finding symbols either from debug code (if present) or from a SYM file in 
  1514.       order to write more meaningful trap logs. See the top of except.c for 
  1515.       details. 
  1516.  
  1517.      excHandlerQuiet is similar to excHandlerPlus in that it uses a longjmp() 
  1518.       also, but neither is this reported to the user nor is the logfile written 
  1519.       to (that's why it's "quiet"). 
  1520.  
  1521.       This is used in places where exceptions have ben known to occur and 
  1522.       there's no way to get around them. I created this handler for V0.80 
  1523.       because I found out that somIsObj() is not a fail-safe routine to find 
  1524.       out if a SOM pointer is valid, even though IBM claims it is. 
  1525.  
  1526.       (These were the strange errors in the Worker thread which appeared in 
  1527.       V0.71 when folders with subfolders were deleted, because the Worker 
  1528.       thread then tried to access these objects when the folder was populated 
  1529.       right before deletion.) 
  1530.  
  1531.       So I created the wpshCheckObject func which can return FALSE, using this 
  1532.       handler, if access to the object fails. 
  1533.  
  1534.  
  1535. ΓòÉΓòÉΓòÉ 7. Adding Features to XWorkplace ΓòÉΓòÉΓòÉ
  1536.  
  1537.      Overview 
  1538.  
  1539.      Adding a new class 
  1540.  
  1541.      Extending existing XWorkplace classes 
  1542.  
  1543.      The "XWorkplace Setup" object 
  1544.  
  1545.      XWorkplace code you might find useful 
  1546.  
  1547.      Writing an XCenter widget plugin DLL 
  1548.  
  1549.  
  1550. ΓòÉΓòÉΓòÉ 7.1. Overview ΓòÉΓòÉΓòÉ
  1551.  
  1552. This section describes how you can integrate your own code into XWorkplace. 
  1553. Since XWorkplace is now a Netlabs project on the Netlabs CVS server, certain 
  1554. rules must be followed so that the whole thing still works even though several 
  1555. developers might be adding stuff. 
  1556.  
  1557. With XWorkplace V0.9.0, I have restructured the whole directory and makefile 
  1558. system to allow for extending XWorkplace. In any case, the idea is that all 
  1559. XWorkplace classes will reside in one single DLL, XFLDR.DLL, but should be 
  1560. capable of being registered independently. 
  1561.  
  1562. Basically, there are two situations which you need to tell apart: 
  1563.  
  1564.    1. You can add a new class to XWorkplace. That is, you wish to hook your 
  1565.       code into the WPS, but XWorkplace doesn't have a class for this yet. This 
  1566.       situation applies both if you wish to replace a standard WPS class 
  1567.       (example: the spooler class, WPSpool) which XWorkplace doesn't replace 
  1568.       yet, or if you wish to create an all new class. (This only makes a 
  1569.       difference at install time, whether the install program will replace a 
  1570.       class.) 
  1571.  
  1572.    2. You may choose to extend an existing XWorkplace class (either an 
  1573.       XWorkplace replacement for a default WPS class, e.g. XFolder, or a newly 
  1574.       introduced XWorkplace class, e.g. XFldWPS -- the "Workplace Shell" 
  1575.       object). This is much simpler, because you can build on existing code. 
  1576.  
  1577.  
  1578. ΓòÉΓòÉΓòÉ 7.2. Adding a New Class ΓòÉΓòÉΓòÉ
  1579.  
  1580. This section describes what to do if you want to write some all new SOM WPS 
  1581. class, which should be integrated into the main XWorkplace DLL, and describe 
  1582. which files need to be changed to have your stuff compiled into the whole 
  1583. thing. 
  1584.  
  1585.    1. Most importantly, I suggest that you put all your code into a separate 
  1586.       source directory in the XWorkplace SRC\ and INCLUDE\ directory trees. 
  1587.       Please do not put your stuff into SRC\FILESYS, because this will make it 
  1588.       pretty difficult to maintain order. For the purpose of explanations here, 
  1589.       I will assume that your directory is called SRC\YOURDIR\ and your class 
  1590.       is called XWPYourClass. 
  1591.  
  1592.       So first of all, create your two subdirectories (YOURDIR) in INCLUDE and 
  1593.       SRC. 
  1594.  
  1595.    2. Create a new IDL file for your class. As a template, you can use 
  1596.       idl\__sample_dataf.idl, which is a sample for a WPDataFile subclass. 
  1597.  
  1598.       Put your new IDL file into the idl\ directory and modify the makefile in 
  1599.       there to recognize your IDL file. That is, add your header file to the 
  1600.       all: statement and add a corresponding line to the bottom. That's all. 
  1601.       And please, add a comment that you did so. 
  1602.  
  1603.       For the purpose of clarity, I suggest that with your IDL file, you take 
  1604.       one of the existing IDL files as a template. My IDL coding style has 
  1605.       evolved during the last two years, and I now consider the comments etc. 
  1606.       in there pretty lucid in order not to forget anything. Of course, if you 
  1607.       have something better, go ahead. 
  1608.  
  1609.    3. Run the main makefile once. The makefile in idl\ will realize that a new 
  1610.       .IDL file has been added and create headers in include\classes\, a .DEF 
  1611.       file in idl\, and stub C code in src\classes\. 
  1612.  
  1613.    4. Now that you have the stub C file in src\classes, modify the makefile in 
  1614.       src\classes to compile your stub file as well. Add your file to the OBJS 
  1615.       macro, and add dependency rules in the $(OUTPUTDIR)\xxx.obj: style to the 
  1616.       bottom. Again, add a comment that you did so. 
  1617.  
  1618.    5. In SRC\YOURDIR\, write your own makefile which compiles your sources. You 
  1619.       can take the makefile in SRC\FILESYS\ as a template. This makefile is 
  1620.       pretty smart because it automatically recognizes whether it is called 
  1621.       from the main makefile, and if not, it invokes the main makefile, which 
  1622.       in turn will call the sub-makefiles later. Also, that makefile uses the 
  1623.       general makefile include setup.in in the main directory for compiler 
  1624.       setup etc. 
  1625.  
  1626.       Make sure that your makefile writes all .OBJ files into the BIN 
  1627.       directory, which your makefile must create if it doesn't exist yet. 
  1628.       Again, see how the makefile in SRC\FILESYS does this. 
  1629.  
  1630.       Other than that, in SRC\YOURDIR, do whatever you want. 
  1631.  
  1632.    6. Coding. For your C code, make sure that you get the #include's right. 
  1633.       Take a look at any C file in SRC\FILESYS for examples (folder.c is a good 
  1634.       candidate, because it's fairly complex). If you use any headers from 
  1635.       include\shared\, there are certain rules that you must follow, because 
  1636.       these headers require other headers to be included already. 
  1637.  
  1638.       Also, I strongly recommend to always include include\setup.h, because 
  1639.       this will automatically make your code PMPRINTF-enabled. 
  1640.  
  1641.       I don't care about your coding style, but if you want your code to be 
  1642.       documented automatically, you should follow mine, because otherwise 
  1643.       xdoc.exe won't work. See Code documentation for details. 
  1644.  
  1645.    7. Note that the SOM compiler is unable to recognize that several classes 
  1646.       should be put into the same DLL and create a common .DEF file for this 
  1647.       purpose, so you have to do this manually. 
  1648.  
  1649.       So have the SOM compiler create a .DEF file for your class from your .IDL 
  1650.       source file. (The makefile in idl\ will do this automatically if you have 
  1651.       added your header to the all: target.) 
  1652.  
  1653.       Then take the block below the EXPORTS line from the .DEF file and add it 
  1654.       to the bottom of src\shared\xwp.def (which is the module definition file 
  1655.       used for linking the whole XWorkplace DLL). These structures make the SOM 
  1656.       kernel see your class in the DLL. If you don't do this, your class cannot 
  1657.       be registered. 
  1658.  
  1659.    8. Finally, take a look at \makefile. This is the "master makefile" which 
  1660.       links all .OBJ modules into the main XWorkplace DLL (XFLDR.DLL). In that 
  1661.       makefile, there is an OBJS macro which lists all the .OBJ files which are 
  1662.       to be linked together. 
  1663.  
  1664.       Add your .OBJ file(s) to the end of that variable (and please, add a 
  1665.       comment that you did so). 
  1666.  
  1667.  This should work. If you have any questions, feel free to contact me. 
  1668.  
  1669.  
  1670. ΓòÉΓòÉΓòÉ 7.3. Extending Existing XWorkplace Classes ΓòÉΓòÉΓòÉ
  1671.  
  1672. This section describes what to do if the class that you need already exists in 
  1673. XWorkplace. Of course, this requires less setup work, because much of the work 
  1674. has already been done. 
  1675.  
  1676.    1. If you need a new WPS method which isn't overridden yet, modify the IDL 
  1677.       file in IDL\ to suit your needs. 
  1678.  
  1679.       If the method you need is already overridden by XWorkplace, go to 3. 
  1680.  
  1681.    2. If you then re-make XWorkplace, the SOM compiler will automatically get 
  1682.       invoked and modify the sources in SRC\CLASSES and the headers in 
  1683.       INCLUDE\CLASSES accordingly. 
  1684.  
  1685.    3. Again, as said on the previous page, add your own directory to INCLUDE 
  1686.       and SRC. Modify the SOM code of the class you need in SRC\CLASSES to call 
  1687.       your implementation in your SRC\YOURDIR directory. 
  1688.  
  1689.    4. You will need to add your header from INCLUDE\YOURDIR to the SOM class 
  1690.       code file that you modified. Please think of some useful function prefix 
  1691.       for your exported functions so that other programmers (including me) can 
  1692.       find your code more easily. 
  1693.  
  1694.       Don't forget to update src\classes\makefile so that the class code file 
  1695.       will be made dependent on your new header (which you have added to the 
  1696.       SRC\CLASSES code). 
  1697.  
  1698.    5. In SRC\YOURDIR\, write your own makefile which compiles your sources. You 
  1699.       can take the makefile in SRC\FILESYS\ as a template. This makefile is 
  1700.       pretty smart because it automatically recognizes whether it is called 
  1701.       from the main makefile, and if not, it invokes the main makefile, which 
  1702.       in turn will call the sub-makefiles later. Also, that makefile uses the 
  1703.       general makefile include setup.in in the main directory for compiler 
  1704.       setup etc. 
  1705.  
  1706.       Make sure that your makefile writes all .OBJ files into the BIN 
  1707.       directory, which your makefile must create if it doesn't exist yet. 
  1708.       Again, see how the makefile in SRC\FILESYS does this. 
  1709.  
  1710.       Other than that, in SRC\YOURDIR, do whatever you want. 
  1711.  
  1712.    6. Finally, take a look at \makefile. This is the "master makefile" which 
  1713.       links all .OBJ modules into the main XWorkplace DLL (XFLDR.DLL). In that 
  1714.       makefile, there is an OBJS macro which lists all the .OBJ files which are 
  1715.       to be linked together. 
  1716.  
  1717.       Add your .OBJ file(s) to the end of that variable (and please, add a 
  1718.       comment that you did so). 
  1719.  
  1720.  
  1721. ΓòÉΓòÉΓòÉ 7.4. The "XWorkplace Setup" Object ΓòÉΓòÉΓòÉ
  1722.  
  1723. If you have added new code to XWorkplace, you might wonder how to integrate 
  1724. your code into the "XWorkplace Setup" object, most notably, how to add stuff to 
  1725. the "Features" container. 
  1726.  
  1727. This is pretty easy. The "Features" page uses a subclassed container (the code 
  1728. for those checkboxes is in helpers\comctl.c, but this you need not worry 
  1729. about). All you have to do is take a look at src\shared\xsetup.c. The 
  1730. setFeaturesInitPage function is responsible for initializing the container with 
  1731. the features, while the setFeaturesItemChanged function reacts to selection 
  1732. changes in the container. 
  1733.  
  1734. To add something, perform the following steps: 
  1735.  
  1736.    1. Add a dialog item ID to include\dlgids.h, where all the other items of 
  1737.       this kind are (search for ID_XCSI_GENERALFEATURES to find them). 
  1738.  
  1739.    2. Add a string for your setting to the NLS strings (e.g. for English, to 
  1740.       001\xfldr001.rc), using that ID. 
  1741.  
  1742.    3. Add your ID to the FeatureItemsList array in src\shared\xsetup.c. Your 
  1743.       item will then automatically get inserted into the container by 
  1744.       setFeaturesInitPage. 
  1745.  
  1746.    4. Still, in setFeaturesInitPage, you need to add a line which checks the 
  1747.       container checkbox according to the setting (those 
  1748.       ctlSetRecordChecked(hwndFeaturesCnr ... lines). 
  1749.  
  1750.    5. In setFeaturesItemChanged, add a case/switch which reacts to user 
  1751.       changes. 
  1752.  
  1753.  
  1754. ΓòÉΓòÉΓòÉ 7.5. XWorkplace Code You Might Find Useful ΓòÉΓòÉΓòÉ
  1755.  
  1756. This section should help you identify XWorkplace code sections which might also 
  1757. be useful to you. 
  1758.  
  1759.    1. This applies mostly to the code in the HELPERS directory. All of that 
  1760.       code is not dependent on XWorkplace and could be used in any program. 
  1761.       There are lots of Control Program, Presentation Manager and GPI helper 
  1762.       functions which might solve problems that you are having. 
  1763.  
  1764.       To use the helper funcs, simply add #include "helpers\xxx.h" at the top 
  1765.       of your code. See the top of the respective header for additional 
  1766.       #include's which are required by the helper. 
  1767.  
  1768.    2. There are some functions in src\shared\common.c which might be useful to 
  1769.       you, most notably to query some XWorkplace settings and NLS stuff. 
  1770.       cmnQuerySetting will return a global setting, for example, or 
  1771.       cmnMessageBox will display one of the pretty XWorkplace message boxes. 
  1772.  
  1773.    3. To find out how to create a WPAbstract class from scratch, including a 
  1774.       completely new view defined by your class (like the "Class list view"), 
  1775.       you can take a look at xclslist.idl and xclslist.c, which do exactly 
  1776.       this. See the comments in that file for instructions. 
  1777.  
  1778.    4. To create a new settings object (which is not derived from WPSystem), 
  1779.       take a look at XWPSetup, a direct subclass of WPAbstract, which is 
  1780.       implemented this way. 
  1781.  
  1782.    5. For easier maintenance of notebook dialog procs, I have created 
  1783.       src\shared\notebook.c, which does just this using callbacks, so you don't 
  1784.       have to rewrite the same stupid window procedures for each notebook page. 
  1785.       This is used throughout XWorkplace's source code whenever settings pages 
  1786.       are inserted, and has proven to be extremely useful. 
  1787.  
  1788.    6. Finally, src\shared\kernel.c contains code which you can extend for 
  1789.       certain tricky situations. For one, you can extend 
  1790.       krnInitializeXWorkplace to have code executed upon Desktop startup; 
  1791.       secondly, you can add messages to krn_fnwpThread1Object if you need code 
  1792.       to absolutely always execute on thread 1 of PMSHELL.EXE, which cannot be 
  1793.       guaranteed with open views of any kind (especially folder views). 
  1794.  
  1795.  
  1796. ΓòÉΓòÉΓòÉ 7.6. Writing an XCenter Widget Plugin DLL ΓòÉΓòÉΓòÉ
  1797.  
  1798. You can write independent plug-in DLLs for the XCenter to implement XCenter 
  1799. widget classes. This saves you from dealing with all the WPS programming 
  1800. details and even from having to compile the rest of XWorkplace. 
  1801.  
  1802. Detailed documentation for writing plug-in DLLs has been added to the 
  1803. XWorkplace User Guide with V0.9.9. Please see that documentation for details. 
  1804.  
  1805. Still, since you have obviously downloaded the XWorkplace source code, if you 
  1806. are interested, I strongly suggest that you create the XWorkplace code 
  1807. documentation. Then, in the HTML files which are generated, look for the 
  1808. documentation for src\shared\center.c documentation which gives you plenty of 
  1809. introductory information. 
  1810.  
  1811. Several standard XCenter widgets have been created as plugin DLLs to show you 
  1812. how this can be done. Their sources are in the src\widgets directory. In that 
  1813. directory, you will also find ____sample.c, which you can use as a template for 
  1814. your own widgets. 
  1815.  
  1816.  
  1817. ΓòÉΓòÉΓòÉ 8. Miscellaneous WPS Programming Hints ΓòÉΓòÉΓòÉ
  1818.  
  1819.      Some SOM tricks 
  1820.  
  1821.  
  1822. ΓòÉΓòÉΓòÉ 8.1. Some SOM Tricks ΓòÉΓòÉΓòÉ
  1823.  
  1824. In general, XWorkplace is pretty straightforward SOM/WPS code. It overrides a 
  1825. lot of wp* and wpcls* methods. 
  1826.  
  1827. In order to avoid too much confusion, the methods which XWorkplace adds do not 
  1828. carry the usual wp* and wpcls* prefixes, but xwp* and xwpcls* instead. Only 
  1829. "real" XWorkplace SOM methods have this prefix; "normal" functions have other 
  1830. prefixes (see the previous page for a list). 
  1831.  
  1832. As XWorkplace became more complex over time, I have delved quite deeply into 
  1833. SOM. While I still don't fully understand what is going on in the SOM kernel 
  1834. (from what I hear, I guess nobody does) and some bugs in there keep puzzling 
  1835. me, I've found out some interesting stuff. 
  1836.  
  1837. Note: The following is not required to write WPS classes. This is additional 
  1838. information for those who have written WPS classes already and might be 
  1839. interested in some SOM internals. 
  1840.  
  1841. Most of this is related to the "WPS Classes" object (xclslist.c). The SOM logic 
  1842. for this is in classlst.c in clsWPSClasses2Cnr, which can analyze the current 
  1843. SOM runtime environment (which is that of the WPS), i.e. all the classes that 
  1844. have been loaded and query their inheritance hierarchy at runtime. 
  1845.  
  1846. This inserts the WPS class tree as recordcores into a given cnr control. This 
  1847. works with any containers in tree views, so that some XWorkplace dialogs can 
  1848. use this too. Check the sources, there's some interesting stuff. 
  1849.  
  1850. Note that there are quite a number of functions in XWorkplace which take SOM 
  1851. (WPS) objects as a parameter, even though they are not SOM methods. See 
  1852. src\shared\wpsh.c for examples. The reason for this is that resolving SOM 
  1853. methods takes quite a bit of time, and calling regular functions will work just 
  1854. as well, but faster. 
  1855.  
  1856. If you look into the .IH header files created by the SOM compiler, you see that 
  1857. the C bindings for method calls are really all macros #define'd in the header 
  1858. files which translate into more complex C code. 
  1859.  
  1860. Here's an example: if you call _wpQueryStyle(somSelf) in xfldr.c, where this 
  1861. method has not been overridden, the WPObject version of this method should get 
  1862. called. Here's the #define in xfldr.ih for this: 
  1863.  
  1864. #define XFolder_wpQueryStyle WPObject_wpQueryStyle 
  1865.  
  1866. And WPObject_wpQueryStyle is #define'd in wpobject.h from the toolkit headers 
  1867. as follows: 
  1868.  
  1869. #define WPObject_wpQueryStyle(somSelf) \
  1870.     (SOM_Resolve(somSelf, WPObject, wpQueryStyle) \
  1871.     (somSelf))
  1872.  
  1873. Actually, there are more macros related to this, but this is the important one. 
  1874. SOM_Resolve in turn is a macro #define'd in somcdev.h, which calls the SOM 
  1875. kernel function somResolve. That function finally goes through the class method 
  1876. tables to find the actual function address and call it. 
  1877.  
  1878. As as result, not only does compiling of SOM code take ages (because of all the 
  1879. nested macros), but also calling SOM methods does, because as opposed to 
  1880. "static" OO languages such as C++, method resolution is occuring at run-time. 
  1881. IBM says in the SOM docs that calling a SOM method takes at least three times 
  1882. as long as calling a normal C function. 
  1883.  
  1884. Since there is no real need to write functions as SOM methods, except when you 
  1885. want to design a method which can be overriden in subclasses, I have only done 
  1886. so in rare occasions to speed up processing. 
  1887.  
  1888. Here are some other SOM tricks and functions which are not mentioned directly 
  1889. in the WPS reference (but only in the chaotic SOM docs), but these are very 
  1890. useful. Some of this is pretty basic, some might be new to WPS programmers, so 
  1891. I'll list this here: 
  1892.  
  1893.      Since all the SOM stuff is declared in those huge header files, you need 
  1894.       to #include a header file if you need access to certain class-specific 
  1895.       features. 
  1896.  
  1897.       For example, if you write a subclass of WPDataFile and need some 
  1898.       program-object method call (e.g. _wpQueryProgDetails), you need to put 
  1899.       #include <wppgm.h> on top of your code, or the method binding will not be 
  1900.       found. 
  1901.  
  1902.       This is not neccessary if the method is defined for a superclass of your 
  1903.       class, because the SOM headers automatically #include all the parent 
  1904.       classes. That is, for example, you don't need to #include wpfsys.h (for 
  1905.       WPFileSystem) for your WPDataFile subclass. 
  1906.  
  1907.      The most important thing to keep in mind is that all SOM classes are 
  1908.       objects too. They are instances of their respective metaclasses. This 
  1909.       takes some getting used to, but it is this concept only which allows WPS 
  1910.       classes to be created at runtime and for class replacements in the first 
  1911.       place. 
  1912.  
  1913.       That is, for example, any Desktop object is an instance of WPObject 
  1914.       (really one of its subclasses). The WPObject class in turn is an instance 
  1915.       of its metaclass, M_WPObject. 
  1916.  
  1917.       In SOM, the default metaclass for a class is SOMClass. However, the WPS 
  1918.       overrides this behavior to create a unique metaclass for each WPS class, 
  1919.       which is prefixed with M_. Since the metaclass is a class as well, it has 
  1920.       methods too (the so-called "class methods", which operate on class 
  1921.       objects, as opposed to the "instance methods" of the class itself, which 
  1922.       operate on instances of the class -- the Desktop objects). 
  1923.  
  1924.      To access a class object, for any existing class you always have a 
  1925.       corresponding macro which is an underscore plus the class name. That is, 
  1926.       the class object of WPObject can always be obtained with _WPObject. This 
  1927.       is useful for calling class methods, which always need to be invoked on a 
  1928.       class object. So, to call a folder class method, you do something like 
  1929.       _wpclsQueryOpenFolders(_WPFolder). 
  1930.  
  1931.       Note: If a class has been replaced, the macro will not return the 
  1932.       original, but the replacement class. That is, if XWorkplace is installed, 
  1933.       the above example would actually return the XFldObject class object (see 
  1934.       notes below), and methods invoked on the WPObject class object would 
  1935.       actually be resolved for XFldObject. That's how class replacements work 
  1936.       in the first place. See the notes below for more. 
  1937.  
  1938.      BOOL _somIsA(pObject, pClassObject) checks for whether pObject is an 
  1939.       instance of the class specified by pClassObject or one of its subclasses. 
  1940.       This is extensively used in statbars.c to adjust status bar display 
  1941.       depending on the class of a single object which is currently selected. 
  1942.  
  1943.       Example: _somIsA(somSelf, _WPObject) should always be true within the WPS 
  1944.       context, since all WPS classes are subclasses of WPObject. By contrast, 
  1945.       _somIsA(somSelf, _WPFolder) would only return TRUE if somSelf is a WPS 
  1946.       folder. (This would work with _XFolder too, but this would require that 
  1947.       you have access to the XFolder header files and that XFolder replaces 
  1948.       WPFolder. _WPFolder always works, even if WPFolder is replaced, because 
  1949.       _WPFolder would be resolved to point to the replacement class object then 
  1950.       -- e.g. _XFolder.) 
  1951.  
  1952.      PSZ _somGetName(pClassObject) returns the class name specified by 
  1953.       pClassObject, as specified in the IDL file. (That is different from 
  1954.       wpclsQueryTitle.) 
  1955.  
  1956.       Example: _somGetName(_XFldObject) will return "XFldObject". 
  1957.  
  1958.      SOMClass* _somGetParent(pClassObject) returns a parent class. 
  1959.  
  1960.       Examples: _somGetParent(_WPProgram) returns the WPAbstract class object 
  1961.       (_WPAbstract). _somGetParent(_XFolder) should return _WPFolder, unless 
  1962.       there's some other WPFolder replacement class above XWorkplace in the 
  1963.       replacement list. 
  1964.  
  1965.      BOOL _somDescendedFrom(pClass, pClassParent) returns TRUE if pClass is 
  1966.       descended from pClassParent. 
  1967.  
  1968.       Examples: _somDescendedFrom(_WPFolder, _WPObject) should return TRUE. 
  1969.       _somDescendedFrom(_WPFolder, _WPProgram) would return FALSE. 
  1970.  
  1971.      somResolveByName(pClassObject, "method") gives you a function pointer as 
  1972.       implemented by the specified class. You should assign this to a function 
  1973.       pointer variable which matches the function prototype, or otherwise 
  1974.       you'll get crashes. This can be useful if you invoke a SOM method 
  1975.       frequently, for example in a loop on many objects, because then SOM 
  1976.       method resolution has to be done only once. If you used the macros, 
  1977.       resolution would take place for each iteration in the loop. 
  1978.  
  1979.      Class replacements. Nowhere is really documented how class replacements 
  1980.       actually work, except that replacement classes must be direct descendants 
  1981.       of the class which is to be replaced. I assume that class replacements 
  1982.       are a feature of the SOM class manager, of which the WPS class manager is 
  1983.       a descendant (WPClassManager is half documented in the WPS Reference.) At 
  1984.       least there is a documented SOMClassMgr method, somSubstituteClass, which 
  1985.       appears to be doing exactly this job. 
  1986.  
  1987.       From what I've seen, class replacements seem to work this way: Any time a 
  1988.       class object is queried, the class manager does not return the class 
  1989.       object of the specified class, but the object of the replacement class 
  1990.       instead. As a result, all the method calls are not resolved for the 
  1991.       original class, but for the replacement class instead. 
  1992.  
  1993.       Examples: If XFolder replaces WPFolder, wpModifyPopupMenu is not called 
  1994.       for WPFolder, but for XFolder instead, even though the WPS had originally 
  1995.       called it for a folder object. By contrast, for wpQueryIcon, which is not 
  1996.       overridden by XFolder, method resolution leads to the method as 
  1997.       implemented by the parent class, which should be WPFolder, unless some 
  1998.       other class replacements is present. 
  1999.  
  2000.       The class replacement mechanism is most obvious with the class object 
  2001.       macros described above: if you have a _WPFolder in your code, this 
  2002.       returns the class object of XFolder, i.e. _WPFolder == _XWorkplace. So if 
  2003.       you absolutely need the WPFolder class object (which is normally not 
  2004.       necessary, since this would circumvent XFolder's functionality), you use 
  2005.       _WPFolder (which returns the XFolder class object) and then climb up the 
  2006.       class object's inheritance tree using _somGetParent until _somGetName 
  2007.       returns "WPFolder". 
  2008.  
  2009.      To get the class object of any class without having access to its header 
  2010.       files, do the following: 
  2011.  
  2012.             somId    somidThis = somIdFromString("WPObject");
  2013.             SOMClass *pClassObject = _somFindClass(SOMClassMgrObject, somidThis, 0, 0);
  2014.  
  2015.       Note again that _somFindClass will return replacement classes instead of 
  2016.       the originals. (That's how the class object macros work, BTW.) 
  2017.  
  2018.      __get_somRegisteredClasses(SOMClassMgrObject) returns a SOMClassSequence 
  2019.       of all currently registered class objects. This is used by the "WPS 
  2020.       classes" page in the "Workplace Shell" object. See classlst.c for 
  2021.       details. 
  2022.  
  2023.  
  2024. ΓòÉΓòÉΓòÉ 9. Resources on the Internet ΓòÉΓòÉΓòÉ
  2025.  
  2026. This chapter contains all external links referenced in this book.  Each link 
  2027. contained herein is an Unified Resource Locator (URL) to a certain location  on 
  2028. the Internet. Simply double-click on one of them to launch Netscape  with the 
  2029. respective URL. 
  2030.  
  2031.  
  2032. ΓòÉΓòÉΓòÉ 9.1. http://service.boulder.ibm.com/dl/ddk/priv/ddk-d ΓòÉΓòÉΓòÉ
  2033.  
  2034.                   Click below to launch Netscape with this URL:
  2035.  
  2036.                 http://service.boulder.ibm.com/dl/ddk/priv/ddk-d
  2037.  
  2038.  
  2039. ΓòÉΓòÉΓòÉ 9.2. http://www.edm2.com ΓòÉΓòÉΓòÉ
  2040.  
  2041.                   Click below to launch Netscape with this URL:
  2042.  
  2043.                                http://www.edm2.com
  2044.  
  2045.  
  2046. ΓòÉΓòÉΓòÉ 9.3. http://www.labyrinth.net.au/~dbareis/zips_fw/pmf96179.zip ΓòÉΓòÉΓòÉ
  2047.  
  2048.                   Click below to launch Netscape with this URL:
  2049.  
  2050.             http://www.labyrinth.net.au/~dbareis/zips_fw/pmf96179.zip
  2051.