home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: WPS_PM / WPS_PM.zip / xfld085s.zip / progref.inf (.txt) < prev    next >
OS/2 Help File  |  1999-03-15  |  68KB  |  1,655 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. XFolder Programmer's Guide and Reference ΓòÉΓòÉΓòÉ
  3.  
  4.      Notices 
  5.  
  6.      Introduction -- start here 
  7.  
  8.      National Language Support 
  9.  
  10.      The XFolder source code 
  11.  
  12.  
  13. ΓòÉΓòÉΓòÉ 2. Notices and Legalese ΓòÉΓòÉΓòÉ
  14.  
  15.      Licence (CHANGED!) 
  16.  
  17.      GNU Public Licence 
  18.  
  19.  Please see the XFolder Online Reference for more notices. 
  20.  
  21.  
  22. ΓòÉΓòÉΓòÉ 2.1. Licence And Disclaimer ΓòÉΓòÉΓòÉ
  23.  
  24. March 1999 
  25.  
  26. While previous XFolder versions were "plain" freeware, all XFolder versions 
  27. since V0.80 have been placed under the GNU General Public Licence (GPL) Version 
  28. 2. 
  29.  
  30. You can find the full text of the GPL in the plain-text file COPYING in the 
  31. XFolder installation directory. I have added a formatted version of this on the 
  32. next page of this document. 
  33.  
  34. By installing XFolder on your system, you declare your agreement to the terms 
  35. and conditions of the GNU General Public Licence, Version 2, as contained in 
  36. the file COPYING in the XFolder installation directory. 
  37.  
  38. The GPL means more Legalese, but also more rights for you as a user and, if 
  39. applicable, developer. The most obvious change is that XFolder's source code is 
  40. now also released. 
  41.  
  42. The following brief explanations are intended as an introduction to the terms 
  43. and conditions of the GPL only. They are not part of the licence agreement, for 
  44. which only the terms and conditions in the COPYING file shall prevail. 
  45.  
  46.      If you are an XFolder user, not much has changed. You may still use 
  47.       XFolder without any payment to Ulrich M╨ñller. The GPL does not restrict 
  48.       you on this matter, because it only imposes restrictions on distribution 
  49.       and modification of software. However, there is still no warranty 
  50.       whatsoever. If XFolder ruins your system and your work of the last 30 
  51.       years is lost, sorry. (This is not very probable though). Refer to the 
  52.       bottom of the GPL for the detailed disclaimer. 
  53.  
  54.      If you're a distributor, you may still distribute the whole XFolder 
  55.       package. However, the GPL will probably require you to also distribute 
  56.       the complete XFolder source code, which is available in a separate 
  57.       package from the author's WWW homepage. Refer to the GPL for details. 
  58.  
  59.      If you're a developer, you now have the source code, which you may use 
  60.       and modify. However, if you base your own software on XFolder's source 
  61.       code, the GPL will most probably require you to place your work under the 
  62.       GPL also. This means that you cannot use my sources if you don't publish 
  63.       all your sources also. 
  64.  
  65.       Even though I'm publishing the source code, I retain the copyright to 
  66.       what I've written. 
  67.  
  68.       The GPL deals with these issues extensively. Before you use or modify any 
  69.       code parts of XFolder, make sure you read the GPL thoroughly. If your 
  70.       software is GPL'd also, by all means feel free to use my code. If you 
  71.       have any questions, feel free to contact me. 
  72.  
  73.  This licence does not necessarily cover future releases. Ulrich M╨ñller retains 
  74.  the right to modify the licence agreement for future versions. 
  75.  
  76.  And now: have fun with XFolder! 
  77.  
  78.  (C) Copyright 1997-99 Ulrich M╨ñller. 
  79.  
  80.  
  81. ΓòÉΓòÉΓòÉ 2.2. GNU Public Licence ΓòÉΓòÉΓòÉ
  82.  
  83. For a formatted version of the GPL, check the XFolder Online Reference 
  84. ("Notices" section). 
  85.  
  86.  
  87. ΓòÉΓòÉΓòÉ 3. Introduction -- Start Here ΓòÉΓòÉΓòÉ
  88.  
  89. Welcome to the XFolder source code! 
  90.  
  91. Changes made since the initial source code release (which was for V0.80) are 
  92. logged in the changelog.txt file in the root directory of the source package. I 
  93. hope this is fairly complete. 
  94.  
  95. You must unzip this package on a HPFS drive because many files in this package 
  96. contain long file names. 
  97.  
  98. This file covers two different things: 
  99.  
  100.    1. Information about the XFolder C source code. This is mainly of interest 
  101.       for programmers who would like to contribute to XFolder, find bugs, or 
  102.       who are just interested in learning how the thing is functioning. 
  103.  
  104.       Some more legalese: BEFORE USING OR MODIFYING ANY CODE, MAKE SURE YOU 
  105.       READ THE GNU GENERAL Public LICENCE IN ITS ENTIRETY. 
  106.  
  107.       If I find out that you steal from me without complying to the GPL, you'll 
  108.       get into trouble. I am not releasing XFolder's source code to make it 
  109.       easier for shareware or commercial developers to sell better software, 
  110.       but to get freeware programmers to write WPS classes. 
  111.  
  112.       However, if you follow the GPL, you are strongly encouraged to use any of 
  113.       my code. After all, I am also using public code. OS/2 needs more 
  114.       freeware! 
  115.  
  116.       If you have questions regarding licence issues, please contact me. 
  117.  
  118.    2. Information about XFolder National Language Support (NLS). This is of 
  119.       interest for people who would like to translate XFolder only. No 
  120.       knowledge of C programming is required for this. 
  121.  
  122.       See the "NLS Overview" page for more information. 
  123.  
  124.  If you have questions, feel free to contact me at 
  125.  ulrich.moeller@rz.hu-berlin.de. 
  126.  
  127.  But if you want to start writing WPS classes, please don't start asking me 
  128.  things like "What is an IDL file?". If you have never created a WPS class, 
  129.  please read the excellent courses at EDM/2 (www.edm2.com) first, which explain 
  130.  a lot of things to get you started. As far as I know, XFolder is the most 
  131.  complex WPS source code available, and it probably does not serve very well as 
  132.  a WPS beginner's tutorial. 
  133.  
  134.  Thanks! 
  135.  
  136.  
  137. ΓòÉΓòÉΓòÉ 4. The XFolder Source Code ΓòÉΓòÉΓòÉ
  138.  
  139.      Overview 
  140.      Requirements for compiling 
  141.      The /MAIN directory 
  142.      The /HELPERS directory 
  143.      XFolder function prefixes 
  144.      Some SOM tricks 
  145.      XFolder settings 
  146.      Folder window subclassing 
  147.      Menu manipulation 
  148.      Extended sort functions 
  149.      XFolder threads 
  150.      Playing Sounds 
  151.      XShutdown 
  152.      XFolder Exception Handling 
  153.      Debugging XFolder 
  154.      Making XFolder 
  155.  
  156.  
  157. ΓòÉΓòÉΓòÉ 4.1. Overview ΓòÉΓòÉΓòÉ
  158.  
  159. Before going into the details of source code, which is complex enough to get 
  160. even the more experienced programmer confused, please read the chapters in the 
  161. "XFolder internals" chapter of the XFolder Online reference for a first 
  162. introduction to XFolder's basic inner workings. 
  163.  
  164. This will give you a vague idea of what XFolder is doing where and deals with 
  165. the most important concepts only, so you don't get overwhelmed by all the 
  166. details which come in this file. 
  167.  
  168. The different subdirectories contain the different parts of XFolder. 
  169.  
  170.      The /001 directory tree contains all the National Language Support (NLS) 
  171.       for English. 
  172.  
  173.      The MAIN directory contains the XFolder main DLL (XFLDR.DLL) files, which 
  174.       is composed from all the .C sources. These in turn contain all the 
  175.       SOM/WPS classes and some library functions. This DLL loads the NLS DLL 
  176.       (XFLDRxxx.DLL, with xxx being a language code) at WPS bootup or when the 
  177.       language is changed using the "XFolder Internals" settings page. See this 
  178.       page for more. 
  179.  
  180.      The /HELPERS subdirectory contains a lot of C files with helper functions 
  181.       which are independent of XFolder. That is, these can be used with any 
  182.       OS/2 VIO and/or PM program. The functions are grouped into categories. 
  183.       See this page for more. 
  184.  
  185.       The HELPERS dir also contains files from Dennis Bareis' PMPRINTF package, 
  186.       which is available in full from his homepage. Refer to the "Debugging 
  187.       XFolder" section for details. 
  188.  
  189.      The /NETSCDDE subdirectory contains the source code of the Netscape DDE 
  190.       interface and the INF sources. This is pretty straightforward, aside from 
  191.       the messy DDE stuff, which is only half documented, both by IBM and 
  192.       Netscape. 
  193.  
  194.      The /TREESIZE subdirectory contains the source code of the external 
  195.       TREESIZE utility, which is called if you select "Treesize" from a 
  196.       folder's context menu (new with V0.81). 
  197.  
  198.       This might be quite useful to you if you're interested in learning some 
  199.       PM container programming, which I've only begun to understand while 
  200.       developing this utility. This also shows some techniques of how to 
  201.       multithread PM programs without blocking the system, which is not 
  202.       trivial. 
  203.  
  204.      /WPSRESET, /REPCLASS and /XSHUTDWN contain the sources of the little 
  205.       XFolder utilities of the same name. These are described in the "Related 
  206.       Files" section of the XFolder Online Reference. 
  207.  
  208.      /TOOLS contains some tools used by the makefiles. Put these on your PATH 
  209.       before making XFolder. 
  210.  
  211.  
  212. ΓòÉΓòÉΓòÉ 4.2. Required Tools ΓòÉΓòÉΓòÉ
  213.  
  214.      Compiler. With V0.80, I have switched to IBM VisualAge C++ 3.0 to develop 
  215.       XFolder. I have not tried EMX/GCC because I'm too lazy to get used to it, 
  216.       even though it might compile faster. 
  217.  
  218.       I'm not perfectly sure whether I'm using IBM-specific language 
  219.       extensions. I had to switch the language level to "extended" to use some 
  220.       none-POSIX C stuff, and I'm not sure whether this is working with GCC. I 
  221.       have looked up some functions in the EMX docs, such as _beginthread, and 
  222.       these appear to be the same, even though they're not POSIX C. 
  223.  
  224.       If you get these sources compiled with a different compiler, please let 
  225.       me know or supply patches. 
  226.  
  227.      Whatever compiler you use, you need some OS/2 Developer's Toolkit for all 
  228.       the SOM header files. 
  229.  
  230.       The Warp 3 toolkit is sufficient. XFolder does some tricks for Warp 4 
  231.       too, but does it even though I don't have the Warp 4 toolkit. ;-) The 
  232.       Toolkit is also needed for changing NLS files, even though you won't need 
  233.       a compiler for that. 
  234.  
  235.      All the .C files have lots of debugging code which can conditionally be 
  236.       compiled using certain #define's in common.h. 
  237.  
  238.       Only if you enable the debugging code, you need the full PMPRINTF package 
  239.       by Dennis Bareis. You do _not_ need that package if you don't use the 
  240.       debugging #define's (which is the default), so don't worry. 
  241.  
  242.       Check the "Debugging" section of this README for details. 
  243.  
  244.  Also see the "Making XFolder" section for how to rebuild XFolder. 
  245.  
  246.  
  247. ΓòÉΓòÉΓòÉ 4.3. The /MAIN directory ΓòÉΓòÉΓòÉ
  248.  
  249. The code for the XFolder main DLL (XFLDR.DLL) is in /MAIN. It uses a lot of 
  250. code from the /HELPERS directory, which is new with V0.81 and contains all the 
  251. helpers code which could also be used independently of XFolder. See the next 
  252. page for more. 
  253.  
  254. The XFolder package contains many classes, but puts them all into a single DLL. 
  255. This is possible by specifying the same target DLL in the IDL files. One can 
  256. put several classes into one .IDL file (which happens in xfldr.idl for example) 
  257. or spread them across several IDL files too. 
  258.  
  259. Note that the .DEF files are not used, except for one. These files are created 
  260. automatically by the SOM compiler, which cannot however create a single DEF 
  261. file if you use several IDL files for the same DLL. So I created xfjoint.def 
  262. manually, which is used instead for linking. This file exports lots of 
  263. mysterious SOM structures which allow the SOM kernel see the classes in the 
  264. DLL. 
  265.  
  266. The filenames with xf* contain the XFolder WPS classes. The filenames are 
  267. similar to the original WPS header files for the classes which are replaced by 
  268. the XFolder classes. 
  269.  
  270. Here is a short overview. Some of the XFolder concepts are then laid out in 
  271. more detail below: 
  272.  
  273.      xfdataf.* is for XFldDataFile. 
  274.  
  275.      xfdesk.* is for XFldDesktop only. With V0.84, lots of code has been moved 
  276.       to separate files from this file. 
  277.  
  278.      xfdisk.* is for XFldDisk. This just maps a lot of context menu features 
  279.       to the XFolder routines. 
  280.  
  281.      xfldr.* is for the XFolder (WPFolder replacement) class, probably the 
  282.       main part of XFolder. This also has the subclassed folder frame window 
  283.       procedure with all the bells and whistles. See "Folder window 
  284.       subclassing" for details. 
  285.  
  286.       This also contains XfldStartup and and XFldShutdown folders, which are 
  287.       plain subclasses of XFolder. 
  288.  
  289.      xfobj.* is for XFldObject, which is needed to get access to some WPS 
  290.       internals and initialize the XFolder environment. 
  291.  
  292.      xfpgmf.* (new with V0.84) is for XFldProgramFile, which does the icon 
  293.       replacements for executable files. 
  294.  
  295.      xfsys.* used to be XFldSystem, now (V0.80) contains the two classes 
  296.       derived from WPSystem, i.e. XFldWPS and XFldSystem (for the "Workplace 
  297.       Shell" and "OS/2 Kernel" objects, respectively). This contains most of 
  298.       the code for the notebook pages. 
  299.  
  300.  Common header files: 
  301.  
  302.      dlgids.h contains all the dialog id's which are used by both the NLS 
  303.       resource DLLs and the XFolder main DLL. 
  304.  
  305.       DO NOT MESS WITH THIS FILE OR EVERYTHING WILL BLOW UP. This file has 
  306.       grown since the end of 1997 and is not very logical any more. 
  307.  
  308.      common.h contains both the funcs from common.c as well as lots of 
  309.       #define's which are _not_ used by the NLS DLLs to avoid having to 
  310.       recompile them all the time. I have done a lot of cleanup with the 
  311.       common.* files with V0.84. 
  312.  
  313.  Other files: 
  314.  
  315.      apm.* contains the APM power-off code, thanks to ARAKAWA Atsushi, who 
  316.       filled this in (V0.82) (apm* function prefix). 
  317.  
  318.      classlst.* "WPS Classes" dialog and SOM logic (used to be objdlgs.* in 
  319.       V0.80) (cls* function prefix). See "Some SOM Tricks" for details. 
  320.  
  321.      cnrsort.* contains sort functions for container sorting only (used to be 
  322.       xfsort.* in V0.80). See "Extended sort functions" for details. 
  323.  
  324.      common.* contains lots of miscellaneous functions which are used by all 
  325.       parts of XFolder (cmn* function prefix), mostly to deal with XFolder 
  326.       Global Settings and other stuff which is independent of the SOM classes. 
  327.  
  328.      except.* (new with V0.84) contains the XFolder exception handlers which 
  329.       used to be in xfdesk.c (exc* function prefix). See "XFolder exception 
  330.       handling" for details. 
  331.  
  332.      menus.* (new with V0.81) contains all the menu logic which was previously 
  333.       in the xfldr.c file (mnu* function prefix). See "Menu manipulation" for 
  334.       details. 
  335.  
  336.      module.* contains XFolder's _DLL_InitModule function and some more 
  337.       functions to query information about the XFolder DLL (mod* function 
  338.       prefix). 
  339.  
  340.      notebook.* (new with V0.82) contains very useful notebook helper 
  341.       functions, which save me from having to rewrite the same window 
  342.       procedures for every single notebook page. Almost all XFolder notebook 
  343.       pages now use these routines (ntb* function prefix). 
  344.  
  345.      statbars.* (new with V0.81) status bar logic, previously spread across 
  346.       many files (stb* function prefix). 
  347.  
  348.      xshutdwn.* (new with V0.84) now contains all the XShutdown code which 
  349.       used to be in xfdesk.c (xsd* function prefix). See "XShutdown" for 
  350.       details. 
  351.  
  352.      xthreads.c.* (new with V0.84) now contains the Worker and Quick threads, 
  353.       which also used to be in xfdesk.c (xthr* function prefix). See "XFolder 
  354.       threads" for details. 
  355.  
  356.      xwps.c.* (new with V0.84) now contains all kinds of pseudo SOM functions 
  357.       which used to carry the cmn* prefix, but were spread all over the place 
  358.       and thus hard to find. All these functions have been put into this file 
  359.       and given the xwps* prefix. See "Some SOM Tricks" for details. 
  360.  
  361.  And then there's SOUND.DLL, which is compiled from the sound.* files (snd* 
  362.  function prefix; see the "Sounds" section). 
  363.  
  364.  
  365. ΓòÉΓòÉΓòÉ 4.4. The /HELPERS directory ΓòÉΓòÉΓòÉ
  366.  
  367.      animate.* contains helper functions to animate icons and also other 
  368.       animation funcs. 
  369.      dosh.* Control Program helper functions. 
  370.      eas.* contains helper functions to handle extended attributes. 
  371.      gpih.* GPI (graphics) helper functions. 
  372.      linklist.* contains helper functions to handle linked lists. 
  373.      procstat.* modified Kai Uwe Rommel's DosQProc() functions. 
  374.      progbars.* progress bar code. 
  375.      prfh.* contains profile (INI) helper functions. 
  376.      stringh.* contains helper functions to handle strings/texts 
  377.      shapewin.* contains the ShapeWindows library. See the top of shapewin.c 
  378.       for details (new with V0.85). 
  379.      threads.* contains helper functions to synchronize threads. 
  380.      winh.* Win (PM) helper functions. 
  381.      wphandle.* Henk Kelder's WPS handles functions (thanks again, Henk!) 
  382.      prfh.* is new with V0.82 and contains Profile (INI) helper functions. 
  383.  
  384.  
  385. ΓòÉΓòÉΓòÉ 4.5. XFolder Function Prefixes ΓòÉΓòÉΓòÉ
  386.  
  387. With V0.81, I have rearranged a lot of files across many more files to make a 
  388. bit clearer where the different functions reside. I guess nobody was able to 
  389. overlook what was going on where. 
  390.  
  391. In addition, I have renamed many functions, giving them prefixes which show in 
  392. which file they reside: 
  393.  
  394.      anm*   /helpers/animate.* 
  395.      apm*   /main/apm.* 
  396.      cmn*   are now (V0.84) exclusively in /main/common.c. 
  397.      dosh*   /helpers/dosh.* 
  398.      ea*    /helpers/eas.* 
  399.      exc*   /main/except.* (new with V0.84) 
  400.      gpih*   /helpers/gpih.* 
  401.      lst*   /helpers/linklist.* 
  402.      mnu*   /main/menus.* 
  403.      mod*   /main/module.* 
  404.      pbar*   /helpers/progbar.* 
  405.      prfh*   /helpers/prfh.* (new with V0.82) 
  406.      prc*   /helpers/procstat.* 
  407.      shp*   /helpers/shapewin.c (new with V0.85) 
  408.      stb*   /main/statbars.* 
  409.      strh*   /helpers/stringh.* 
  410.      thr*   /helpers/threads.* 
  411.      wph*   /helpers/wphandle.* 
  412.      xsd*   /main/xshutdwn.* (new with V0.84) 
  413.      xthr*   /main/xthreads.* (new with V0.84) 
  414.      xwps*   /main/xwps.* (new with V0.84) 
  415.  
  416.      xf*    SOM instance methods in the /main/xf* files 
  417.      xfcls*  SOM class methods in the /main/xf* files 
  418.  
  419.  
  420. ΓòÉΓòÉΓòÉ 4.6. Some SOM Tricks ΓòÉΓòÉΓòÉ
  421.  
  422. In general, XFolder is pretty straightforward SOM/WPS code. It overrides a lot 
  423. of wp* and wpcls* methods. 
  424.  
  425. In order to avoid too much confusion, the methods which XFolder adds do not 
  426. carry the usual wp* and wpcls* prefixes, but xf* and xfcls* instead. Only 
  427. XFolder SOM methods have this prefix; "normal" functions have other prefixes. 
  428.  
  429. As XFolder became more complex over time, I have delved quite deeply into SOM. 
  430. While I still don't fully understand what is going on in the SOM kernel (from 
  431. what I hear, I guess nobody does) and some bugs in there keep puzzling me, but 
  432. I've found out some interesting stuff. 
  433.  
  434. Most of this is related to the "WPS Classes" page in the new "Workplace Shell" 
  435. object (xfsys.*). The SOM logic for this is in classlst.c in clsWPSClasses2Cnr, 
  436. which can analyze the current SOM runtime environment (which is that of the 
  437. WPS), i.e. all the classes that have been loaded and query their inheritance 
  438. hierarchy at runtime. 
  439.  
  440. This inserts the WPS class tree as recordcores into a given cnr control. This 
  441. works with any containers in tree views, so that some XFolder dialogs can use 
  442. this too. Check the sources, there's some interesting stuff. 
  443.  
  444. Note that there are quite a number of functions in XFolder which take SOM (WPS) 
  445. objects as a parameter, even though they are not SOM methods. See xwps.c for 
  446. examples. The reason for this is that resolving SOM methods takes quite a bit 
  447. of time, and calling regular functions will work just as well, but faster. 
  448.  
  449. If you look into the .IH header files created by the SOM compiler, you see that 
  450. the C bindings for method calls are really all macros #define'd in the header 
  451. files which translate into more complex C code. 
  452.  
  453. Here's an example: if you call _wpQueryStyle(somSelf) in xfldr.c, where this 
  454. method has not been overridden, the WPObject version of this method should get 
  455. called. Here's the #define in xfldr.ih for this: 
  456.  
  457. #define XFolder_wpQueryStyle WPObject_wpQueryStyle 
  458.  
  459. And WPObject_wpQueryStyle is #define'd in wpobject.h from the toolkit headers 
  460. as follows: 
  461.  
  462. #define WPObject_wpQueryStyle(somSelf) \
  463.     (SOM_Resolve(somSelf, WPObject, wpQueryStyle) \
  464.     (somSelf))
  465.  
  466. Actually, there are more macros related to this, but this is the important one. 
  467. SOM_Resolve in turn is a macro #define'd in somcdev.h, which calls the SOM 
  468. kernel function somResolve. That function finally goes through the class method 
  469. tables to find the actual function address and call it. 
  470.  
  471. As as result, not only does compiling of SOM code take ages (because of all the 
  472. nested macros), but also calling SOM methods does, because as opposed to 
  473. "static" OO languages such as C++, method resolution is occuring at run-time. 
  474. IBM says in the SOM docs that calling a SOM method takes at least three times 
  475. as long as calling a normal C function. 
  476.  
  477. Since there is no real need to write functions as SOM methods, except when you 
  478. want to design a method which can be overriden in subclasses, I have only done 
  479. so in rare occasions to speed up processing. 
  480.  
  481. Here are some other SOM tricks and functions which are not mentioned directly 
  482. in the WPS reference (but only in the chaotic SOM docs), but these are very 
  483. useful and should be known to everyone: 
  484.  
  485.      Since all the SOM stuff is declared in those huge header files, you need 
  486.       to #include a header file if you need access to certain class-specific 
  487.       features. 
  488.  
  489.       For example, if you write a subclass of WPDataFile and need some 
  490.       program-object method call (e.g. _wpQueryProgDetails), you need to put 
  491.       #include <wppgm.h> on top of your code, or the method binding will not be 
  492.       found. 
  493.  
  494.       This is not neccessary if the method is defined for a superclass of your 
  495.       class, because the SOM headers automatically #include all the parent 
  496.       classes. That is, for example, you don't need to #include wpfsys.h (for 
  497.       WPFileSystem) for your WPDataFile subclass. 
  498.  
  499.      The most important thing to keep in mind is that all SOM classes are 
  500.       objects too. They are instances of their respective metaclasses. This 
  501.       takes some getting used to, but it is this concept only which allows WPS 
  502.       classes to be created at runtime and for class replacements in the first 
  503.       place. 
  504.  
  505.       That is, for example, any WPS object is an instance of WPObject (really 
  506.       one of its subclasses). The WPObject class in turn is an instance of its 
  507.       metaclass, M_WPObject. The WPObject class has a so-called "class object" 
  508.       at runtime, the metaclass does not. 
  509.  
  510.      For any existing class you always have a corresponding macro which is an 
  511.       underscore plus the class name. That is, the class object of WPObject can 
  512.       always be obtained with _WPObject. 
  513.  
  514.      BOOL _somIsA(pObject, pClassObject) checks for whether pObject is an 
  515.       instance of the class specified by pClassObject or one of its subclasses. 
  516.       This is extensively used in statbars.c to adjust status bar display. 
  517.  
  518.       Example: _somIsA(somSelf, _WPObject) should always be true within the WPS 
  519.       context, since all WPS classes are subclasses of WPObject. 
  520.  
  521.      PSZ _somGetName(pClassObject) returns the actual name of the class 
  522.       specified by pClassObject, as specified in the IDL file. (That is 
  523.       different from wpclsQueryTitle.) 
  524.  
  525.       Example: _somGetName(_XFldObject) will return "XFldObject". 
  526.  
  527.      SOMClass* _somGetParent(pClassObject) returns a parent class. 
  528.  
  529.       Examples: _somGetParent(_WPProgram) returns the WPAbstract class object 
  530.       (_WPAbstract). _somGetParent(_XFolder) should return _WPFolder, unless 
  531.       there's some other WPFolder replacement class above XFolder in the 
  532.       replacement list. 
  533.  
  534.      BOOL _somDescendedFrom(pClass, pClassParent) returns true if pClass is 
  535.       descended from pClassParent. 
  536.  
  537.       Example: _somDescendedFrom(_WPFolder, _WPObject) should return TRUE. 
  538.  
  539.      somResolveByName(pClassObject, "method") gives you a function pointer as 
  540.       implemented by the specified class. You should assign this to a function 
  541.       pointer variable which matches the function prototype, or otherwise 
  542.       you'll get crashes. 
  543.  
  544.      Class replacements. Nowhere is really documented how class replacements 
  545.       actually work, except that replacement classes must be direct descendants 
  546.       of the class which is to be replaced. I assume that class replacements 
  547.       are a feature of the SOM class manager, of which the WPS class manager is 
  548.       a descendant (WPClassManager is half documented in the WPS Reference.) At 
  549.       least there is a documented SOMClassMgr method, somSubstituteClass, which 
  550.       appears to be doing exactly this job. 
  551.  
  552.       From what I've seen, class replacements seem to work this way: Any time a 
  553.       class object is queried, the class manager does not return the class 
  554.       object of the specified class, but the object of the replacement class 
  555.       instead. As a result, all the method calls are not resolved for the 
  556.       original class, but for the replacement class instead. 
  557.  
  558.       Examples: wpModifyPopupMenu is not called for WPFolder, but for XFolder 
  559.       instead, even though the WPS had called it for a folder object. By 
  560.       contrast, for wpQueryIcon, which is not overridden by XFolder, method 
  561.       resolution leads to the method as implemented by the parent class, which 
  562.       should be WPFolder, unless some other class replacements is present. 
  563.  
  564.       The class replacement mechanism is most obvious with the class object 
  565.       macros described above: if you have a _WPFolder in your code, this 
  566.       returns the class object of XFolder, i.e. _WPFolder == _XFolder. So if 
  567.       you absolutely need the WPFolder class object, you call _XFolder and then 
  568.       climb up the class object's inheritance tree using _somGetParent until 
  569.       _somGetName returns "WPFolder". 
  570.  
  571.      To get the class object of any class without having access to its header 
  572.       files, do the following: 
  573.  
  574.             somId    somidThis = somIdFromString("WPObject");
  575.             SOMClass *pClassObject = _somFindClass(SOMClassMgrObject, somidThis, 0, 0);
  576.  
  577.       Note again that _somFindClass will return replacement classes instead of 
  578.       the originals. (That's how the class object macros work, BTW.) 
  579.  
  580.      __get_somRegisteredClasses(SOMClassMgrObject) returns a SOMClassSequence 
  581.       of all currently registered class objects. This is used by the "WPS 
  582.       classes" page in the "Workplace Shell" object. See classlst.c for 
  583.       details. 
  584.  
  585.  
  586. ΓòÉΓòÉΓòÉ 4.7. XFolder Settings ΓòÉΓòÉΓòÉ
  587.  
  588. XFolder uses two kinds of settings: global and instance settings. 
  589.  
  590. The global settings are set both in the "Workplace Shell" object and on the 
  591. "XDesktop" notebook page and are stored in the "XFolder" app in OS2.INI. All 
  592. the global notebook logic is in xfsys.c. 
  593.  
  594. XFolder's code accesses these settings via a large structure called 
  595. GLOBALSETTINGS (suprise!) defined in common.h, to which a pointer be obtained 
  596. using cmnQueryGlobalSettings (common.c). 
  597.  
  598. By contrast, the individual object settings are stored in instance data, which 
  599. is declared in the .IDL files. Most of these are stored and retrieved using the 
  600. normal WPS mechanism (wpSaveDeferred/wpRestoreData) and can have a certain 
  601. "transparent" value, which means that the global setting is to be used instead. 
  602.  
  603.  
  604. ΓòÉΓòÉΓòÉ 4.8. Subclassing Folder Windows ΓòÉΓòÉΓòÉ
  605.  
  606. XFolder subclasses all WPFolder frame windows to intercept a large number of 
  607. messages. This is needed for the majority of XFolder's features, which are not 
  608. directly SOM/WPS-related, but are rather straight PM programming. 
  609.  
  610. The trick is just how to get "past" the WPS, which does a lot of hidden stuff 
  611. in its method code. By subclassing the folder frames, we get all the messages 
  612. which are being sent or posted to the folder and can thus modify the WPS's 
  613. behavior, since most of the default WPS methods are only called in response to 
  614. certain folder messages. 
  615.  
  616. Subclassing is done in XFolder::wpOpen after having called the parent, which 
  617. returns the new frame window handle. 
  618.  
  619. XFolder's subclassed frame window proc is called fnwpSubclassedFolderFrame 
  620. (also in xfldr.c). Take a look at it, it's one of the most interesting parts of 
  621. XFolder. It handles status bars (which are frame controls), tree view 
  622. auto-rolling, special menu features, the "folder content" menus and more. 
  623.  
  624. This gives us the following hierarchy of window procedures: 
  625.  
  626.    1. our fnwpSubclassedFolderFrame, first, followed by 
  627.    2. WPS folder frame window subclass, followed by 
  628.    3. WC_FRAME's window procedure, followed by 
  629.    4. WinDefWindowProc last. 
  630.  
  631.  If additional WPS enhancers are installed (e.g. Object Desktop), they will 
  632.  appear at the top of the chain also. I guess it depends on the hierarchy of 
  633.  replacement classes in the WPS class list which one sits on top. 
  634.  
  635.  In order to be able to relate the original frame window proc to a folder frame 
  636.  (which can be different for each WPFolder window), XFolder maintains a global 
  637.  linked list of PSUBCLASSEDLISTITEM structures (declared in common.h). This 
  638.  might be a bit slow, but I have found no other way to store the original 
  639.  window proc. Using window words does not work (believe me: it does crash the 
  640.  WPS), because the window words seem to be used by the WPS already, and (of 
  641.  course) this is not documented. If you have a better idea for this, let me 
  642.  know. 
  643.  
  644.  As with all linked lists, XFolder uses the lst* functions in 
  645.  /helpers/linklist.c for adding/removing/searching etc. list items. I have 
  646.  developed these myself. If you have developed better funcs for doing this, let 
  647.  me know. I don't claim mine are too effective, but I have found no better ones 
  648.  which are thread-safe, and mine are because they allow for using mutex 
  649.  semaphores. 
  650.  
  651.  
  652. ΓòÉΓòÉΓòÉ 4.9. Menu Manipulation ΓòÉΓòÉΓòÉ
  653.  
  654. This is perhaps the most complex part of XFolder. After all, this is what I've 
  655. started with, so some code parts may well be unchanged since December '97, when 
  656. I neither knew much about C nor about WPS programming. 
  657.  
  658. With V0.81, all the logic for manipulating and evaluating context menus has 
  659. been moved to a new file, menus.c. All these functions have been given the mnu* 
  660. prefix to make this a bit clearer. 
  661.  
  662. The XFolder classes override wpModifyPopupMenu and wpMenuItem[Help]Selected for 
  663. almost every replacement class. These overrides either handle the new context 
  664. menu items in that method code or, for XFolder and XFldDisk, call the functions 
  665. in menus.c, because these two classes share many common menu items, so we can 
  666. share most of the code also. 
  667.  
  668. All newly inserted menu items use variable menu IDs. You can tell this from 
  669. their #define names, which have an _OFS_ in their name (check dlgids.h). To all 
  670. these values, XFolder adds the offset that is specified on the "XFolder 
  671. internals" notebook page. 
  672.  
  673. For an introduction to how the config folder menu items work, see the "XFolder 
  674. Internals" section in the XFolder Online Reference. XFolder uses a fairly 
  675. obscure system of global variables to be able to relate menu items to their 
  676. intended functions. All the variable menu items are stored in a global linked 
  677. list when the context menu is opened for a folder. In each list item, XFolder 
  678. also stores what kind of object (template, program object, folder content item 
  679. etc.) the menu item represents. This list is then examined by 
  680. wpMenuItemSelected to perform the corresponding action (create a new object, 
  681. start program etc.). After that, the list is destroyed, so it only eats up 
  682. memory while the context menu is open. All this code is now (V0.81) in menus.c. 
  683.  
  684. The folder content menus are initially only inserted as empty stubs. They are 
  685. only filled with items when they're opened: XFolder intercepts WM_INITMENU in 
  686. the subclassed folder frame proc (fnwpSubclassedFolderFrame, xfldr.c) and then 
  687. populates the menu. These menu items are stored in the global list too and 
  688. marked as folder content menu items so that wpMenuItemSelected will then simply 
  689. open the corresponding WPS object. The folder content code has now been moved 
  690. to menus.c also. 
  691.  
  692. Painting the icons is then done using owner-draw menu items; the messages which 
  693. are necessary for this are also intercepted in fnwpSubclassedFolderFrame and 
  694. then call corresponding functions in menus.c. 
  695.  
  696. Folder content menus are also subclassed to be able to intercept right-mouse 
  697. button clicks. The new window proc for this is called (suprise!) 
  698. fnwpFolderContentMenu and resides in xfldr.c. 
  699.  
  700. The xfSelectingMenuItem method introduced in V0.80 has been removed again with 
  701. V0.81 due to the problems with SOM multiple inheritance. 
  702.  
  703.  
  704. ΓòÉΓòÉΓòÉ 4.10. Extended Sort Functions ΓòÉΓòÉΓòÉ
  705.  
  706. The default WPS sort functions are a mess, and I suppose IBM knows that, since 
  707. they have hardly documented them at all. 
  708.  
  709. So here's what I found out. 
  710.  
  711. The default sort criteria are all related to object details. That is, to 
  712. implement a sort criterion, you have to have a corresponding object detail, as 
  713. defined in the wpclsQueryDetailsInfo and wpQueryDetailsData methods. 
  714.  
  715. There are many more object details than those shown in folder Details views. I 
  716. have counted 23 here (but your results may vary), and since there are only 13 
  717. columns in Details view, there should be about 10 invisible details. (Side 
  718. note: You can view all of them by turning to the "Include" page of any folder 
  719. and pressing the "Add..." button.) 
  720.  
  721. Most of the details are defined in WPFileSystem's override of 
  722. wpclsQueryDetailsInfo, and if certain sort flags are specified there (even when 
  723. the details column is never visible), the WPS will make this detail available 
  724. as a sort criterion. That is, it inserts the column title in the "Sort" 
  725. submenu, shows it on the "Sort" page, and sets some corresponding comparison 
  726. function for the folder containers automatically. 
  727.  
  728. This works beautifully for "real" subclasses of default WPS classes. For 
  729. example, you can create some subclass of WPDataFile, e.g. "WPAddress" for 
  730. storing addresses, define new object details for that class, set the "folder 
  731. sort class" of a folder to WPAddress, and you can then sort the folder 
  732. according to addresses automatically. 
  733.  
  734. So, in theory, the whole details concept is great. You add new details to a 
  735. class, and the WPS can automatically sort, display the details, and even set 
  736. the "Include" options for folder accordingly. 
  737.  
  738. But unfortunately, all the details/include/sort stuff is yet another example of 
  739. another great IBM concept which was only half implemented. I have found out the 
  740. hard way that XFolder cannot use this approch to extend the default sort 
  741. criteria. This is for the following reasons (believe me, I've tried all of the 
  742. following): 
  743.  
  744.    1. It is impossible to add new default details to an override of 
  745.       WPFileSystem. Even if WPFileSystem is replaced with another class, 
  746.       wpQueryFldrSortClass and wpQueryFldrDetailsClass do not return the 
  747.       replacement class object, but the original WPFilesystem class object. I 
  748.       have then tried to replace these two methods too, and details/sorting 
  749.       would still not always work. There seem to be some ugly kludges in the 
  750.       WPS internally. 
  751.  
  752.    2. Apparently, two sort criteria ("Name" and "Type") do not correspond to 
  753.       any details columns. Normally, sort criteria are specified by passing the 
  754.       corresponding details column to a sort function (see 
  755.       wpIsSortAttribAvailable, for example). However, these two criteria have 
  756.       indices of "-2" and "-1", so there seems to be some hard-coded special 
  757.       case check in the WPS again. The "Type" criterion is even available when 
  758.       WPObject is selected as the folder sort class, but WPObject does not 
  759.       define that detail. So who knows. 
  760.  
  761.    3. The documentation for CLASSFIELDINFO is incomplete and partly incorrect. 
  762.       I have tried to specify new sort functions in there, and the WPS would 
  763.       just hang. Apparently the function prototypes are not correct, because my 
  764.       own comparison function would never reach its first instruction before 
  765.       the hang. 
  766.  
  767.    4. The wpQueryFldrSort and wpSetFldrSort methods are completely obscure. 
  768.       They are prototyped using a PVOID parameter, and the documentation says 
  769.       this should point to a SORTFASTINFO structure. But for one, this 
  770.       structure is defined nowhere in the headers, and even more importantly, 
  771.       the data passed to these methods does not correspond to the description 
  772.       in the WPS reference. The first field in the structure is definitely no 
  773.       sort function. So we have one more mystery there. 
  774.  
  775.    5. The most important limitation was however that there are no default 
  776.       settings for sorting. The default sort criterion is always set to "Name", 
  777.       and "Always sort" is always off. This is hard-coded into WPFolder and 
  778.       cannot be changed. There is not even an instance method for querying or 
  779.       setting the "Always sort" flag, let alone a class method for the default 
  780.       values. The only documented thing is the ALWAYSSORT setup string. 
  781.  
  782.  Besides, the whole concept is so complicated that I only understood it now 
  783.  after having debugged all the related methods for several days. I don't think 
  784.  many users appreciate the flexibility of that concept or even know what "sort 
  785.  classes" or "details classes" are about, even though there may be certain WPS 
  786.  classes that use this concept. 
  787.  
  788.  The XFolder approach. It's basically a "brute force" method. XFolder lets the 
  789.  WPS add the default sort features to context menus as usual, then adds its 
  790.  own, and just intercepts all the menu ID's in wpMenuItemSelected. 
  791.  
  792.  I have then written a complete new set of container sort comparison functions 
  793.  (in cnrsort.*) which do the job. So it's not the WPS at all any more which 
  794.  does the sorting, but XFolder, and XFolder uses its own set of settings for 
  795.  all this. See cmnSetCnrSort in xfldr.c for how this is done. 
  796.  
  797.  As you know, XFolder replaces the "Sort" page in folder settings notebooks 
  798.  altogether too. 
  799.  
  800.  In addition, XFolder overrides the wpSetFldrSort method, which apparently gets 
  801.  called every time the WPS tries to sort a folder. That is, normally, if one of 
  802.  the "Sort" menu items would get called, but these are intercepted already by 
  803.  XFolder. The override is still needed though because the WPS calls that method 
  804.  frequently when "Always sort" is on also, e.g. when you rename a file. 
  805.  
  806.  Finally, there's a real neat hack to get access to the internal folder sort 
  807.  settings, i.e. the settings that reside in the memory allocated by the 
  808.  original WPFolder class. In wpRestoreData, which gets called when an object is 
  809.  awakened, WPFolder always attempts to restore its folder sort settings from 
  810.  the instance settings. 
  811.  
  812.  Since the caller always passes a block of memory to which wpRestoreData should 
  813.  write if the data was found, we can intercept that pointer and store it in 
  814.  XFolder's instance data. We can therefore manipulate the "Always sort" flag 
  815.  also. 
  816.  
  817.  BTW, this can be used as a general approach to get access to WPS-internal 
  818.  data, if a corresponding ulKey exists. Just override wpRestoreData (or the 
  819.  other restore methods) and check for what keys they get called. Most of them 
  820.  are declared in wpfolder.h in the Toolkit headers. 
  821.  
  822.  
  823. ΓòÉΓòÉΓòÉ 4.11. XFolder Threads ΓòÉΓòÉΓòÉ
  824.  
  825. XFolder is quite heavily multi-threaded and offloads most tasks which are 
  826. probable to take some time to the so-called "Worker" thread. XFolder uses mutex 
  827. semaphores all over the place to serialize access to global data structures. 
  828.  
  829. Note that with V0.84, all the additional thread code has been moved from 
  830. xfdesk.c to a new xthreads.c file. This makes more sense and also reduces the 
  831. danger of unwanted side effects with large code files. 
  832.  
  833. The Worker thread creates an object window to which other functions post 
  834. messages using xthrPostWorkerMsg to offload work. This object window's window 
  835. procedure is called xthr_fnwpWorkerObject, the main thread function is called 
  836. xthr_fntWorkerThread. 
  837.  
  838. For example, the Worker thread maintains the global linked list of currently 
  839. awake WPS objects. XFldObject::wpObjectReady post WOM_ADDAWAKEOBJECT to the 
  840. Worker thread, which then adds the object to that list. (This list is needed by 
  841. XShutdown to store all the awake WPS objects; see the XFolder Online Reference 
  842. for details). 
  843.  
  844. The Worker thread is created in XFldObject::wpclsInitData, which calls 
  845. xthrInitializeThreads. This is probably the first SOM method called when the 
  846. WPS is booting up, so I put this in here to allow the Worker thread to keep 
  847. track of really _all_ the objects. 
  848.  
  849. The Worker thread runs at "Idle" priority, unless more than 300 messages have 
  850. piled up in its message queue. In this case, the priority is temporarily raised 
  851. to "Regular" and set back if the message count goes below 10 again. This can 
  852. happen when opening folders with a very large number of objects. 
  853.  
  854. In addition, XFolder uses the "Quick" thread running at a high "Regular" 
  855. priority for things which won't take long but should not block the main WPS 
  856. (Workplace) thread. This thread creates an object window also.  For example, 
  857. the new system sounds are played here. 
  858.  
  859. The Quick thread is created together with the Worker thread and also displays 
  860. the most beautiful XFolder logo when it's started. 
  861.  
  862.  
  863. ΓòÉΓòÉΓòÉ 4.12. Playing Sounds ΓòÉΓòÉΓòÉ
  864.  
  865. The new system sounds are played in the "Quick" thread with high regular 
  866. priority. Check fntQuickThread and fnwpQuickObject for details about how this 
  867. is implemented using MMOS/2. 
  868.  
  869. There are two above-average programming tricks related to this: 
  870.  
  871.      For one, nowhere is documented how to access and modify the system sounds 
  872.       that appear in the "Sound" object. I have accidently discovered that this 
  873.       is actually fairly easy: these are stored in MMPM.INI in the MMOS/2 
  874.       directory. Each sound has an index in that file, which I have declared in 
  875.       common.h (those MMSOUND_* #define's). These should be the same on every 
  876.       system. The INI data then contains a "<soundfile>#<description>#<volume>" 
  877.       string. Check cmnQuerySystemSound in common.c for details. 
  878.  
  879.      With V0.82, the actual playing of the sounds has been moved to a separate 
  880.       SOUND.DLL because previously XFolder would refuse to install on systems 
  881.       where MMPM/2 was not installed. This was due to the fact that if you link 
  882.       a DLL against the MMPM/2 library functions, loading of the DLL fails if 
  883.       these imports cannot be resolved. (Naturally, you don't get an error 
  884.       message other than FALSE from the SOM kernel. This has taken me days to 
  885.       find out.) 
  886.  
  887.       Now, if loading of SOUND.DLL fails (either because it's not there or 
  888.       because the MMPM/2 imports of that DLL cannot be resolved), the new 
  889.       system sounds are silently disabled. This happens in 
  890.       xthrInitializeThreads. 
  891.  
  892.       Also, I've added much more sophisticated MMPM/2 messaging to check for 
  893.       whether the waveform device is actually available. So playing sounds is a 
  894.       process of communication between the Quick thread and SOUND.DLL now. See 
  895.       the top of sound.c for more explanations. 
  896.  
  897.  
  898. ΓòÉΓòÉΓòÉ 4.13. XShutdown ΓòÉΓòÉΓòÉ
  899.  
  900. XShutdown (i.e. the "eXtended Shutdown" and "Restart WPS" features) has been 
  901. moved from xfdesk.c to a new file, xshutdwn.c, with V0.84. 
  902.  
  903. XShutdown starts two additional threads to close all the windows. This is 
  904. described in detail in the "XFolder Internals" section of the XFolder Online 
  905. Reference. I have also tried to put plenty of comments into the sources. 
  906.  
  907.  
  908. ΓòÉΓòÉΓòÉ 4.14. XFolder Exception Handling ΓòÉΓòÉΓòÉ
  909.  
  910. XFolder registers additional exception handlers in certain parts where I 
  911. considered worth it. 
  912.  
  913. With "worth it" I mean the following situations: 
  914.  
  915.    1. Certain code parts crashed on my system and these parts seemed 
  916.       error-prone enough to me to outweigh the performance loss of registering 
  917.       and deregistering exception handlers. 
  918.  
  919.    2. Exception handlers must be registered for all additional threads. If no 
  920.       exception handling was registered there, crashes would take the whole WPS 
  921.       down, because the default WPS exception handler only deals with the 
  922.       default WPS threads. 
  923.  
  924.    3. Exception handlers must also be registered every time mutex semaphores 
  925.       are used. If a code part crashes while a mutex semaphore has been 
  926.       requested by a function, all other threads waiting for that semaphore to 
  927.       be released will be blocked forever. And I mean forever, because even 
  928.       DosKillProcess won't be able to terminate that thread. You'd have to 
  929.       reboot to get out of this. So the exception handler must always check for 
  930.       whether a mutex semaphore is currently owned by the thread and, if so, 
  931.       release it. 
  932.  
  933.  XFolder does not use the VAC++ library funcs for all this, but installs its 
  934.  own set of quite complex exception handlers (using DosSetExceptionHandler()). 
  935.  With V0.84, the exception handlers have been moved from xfdesk.c to a new 
  936.  file, except.c. That makes more sense. 
  937.  
  938.  Also, I have created a few handy macros which automatically register and 
  939.  deregister the XFolder exception handlers. This avoids the frequent problem 
  940.  that one forgets to deregister an exception handler, which leads to really 
  941.  awkward problems which are almost impossible to debug. Those macros are called 
  942.  TRY_xxx and CATCH to mimic at least some C++ syntax. See except.c for how to 
  943.  install these macros. 
  944.  
  945.  The XFolder exception handlers are the following: 
  946.  
  947.      excHandlerPlus is the one that makes the loud sounds and writes the 
  948.       XFLDTRAP.LOG file which is well-known to many XFolder users (grin). It 
  949.       uses a longjmp() to get back to the function, which might then react to 
  950.       that exception by trying to restore some safe state of the thread. See 
  951.       the func header for details about how this works. 
  952.  
  953.       This handler is used by all the additional XFolder threads and also by 
  954.       the subclassed folder frame and folder content menu window procs. This 
  955.       slows down the system a bit because the handler must be registered and 
  956.       deregistered for each message that comes in, but there's no other way to 
  957.       do this. (I think.) 
  958.  
  959.       With V0.84, I have added lots of debugging code which I found in the 
  960.       EXCEPTQ.ZIP package at Hobbes. The exception handlers are now capable of 
  961.       finding symbols either from debug code (if present) or from a SYM file. 
  962.       See the top of except.c for details. 
  963.  
  964.      excHandlerQuiet is similar to excHandlerPlus in that it uses a longjmp() 
  965.       also, but neither is this reported to the user nor is the logfile written 
  966.       to (that's why it's "quiet"). 
  967.  
  968.       This is used in places where exceptions have ben known to occur and 
  969.       there's no way to get around them. I created this handler for V0.80 
  970.       because I found out that somIsObj() is not a fail-safe routine to find 
  971.       out if a SOM pointer is valid, even though IBM claims it is. 
  972.  
  973.       (These were the strange errors in the Worker thread which appeared in 
  974.       V0.71 when folders with subfolders were deleted, because the Worker 
  975.       thread then tried to access these objects when the folder was populated 
  976.       right before deletion.) 
  977.  
  978.       So I created the xwpsCheckObject func which can return FALSE, using this 
  979.       handler, if access to the object fails. 
  980.  
  981.  
  982. ΓòÉΓòÉΓòÉ 4.15. Debugging XFolder ΓòÉΓòÉΓòÉ
  983.  
  984. Debugging WPS applications can be really tiresome, because you have to restart 
  985. the WPS for every tiny change you made to the source codes to take effect. And, 
  986. as with any PM program, you can't just printf() stuff to the screen. Even 
  987. worse, it's hard to use the PM debugger, because you have to start the whole 
  988. WPS (PMSHELL.EXE) with it, since XFLDR.DLL is no standalone application. 
  989.  
  990. So I had to look for something else. 
  991.  
  992. Those _Pmpf(("xxx")) thingies are for the magnificent PMPRINTF package by 
  993. Dennis Bareis. These only display anything if the proper DEBUG_xxx #define's 
  994. are set on top of common.h. For the release version of XFolder, all these flags 
  995. have been disabled, so no additional code is produced at all. You thus don't 
  996. have to remove the commands to speed up XFolder, because this wouldn't make any 
  997. difference. 
  998.  
  999. Some files from the PMPRINTF package are included so that you can compile. The 
  1000. PM interface which actually displays the messages is not however. Check Dennis 
  1001. Bareis' homepage at http://www.ozemail.com.au/~dbareis/ where you'll find tons 
  1002. of other useful utilities too. 
  1003.  
  1004. However, to really use PMPRINTF, you'll have to put some DLLs on your LIBPATH. 
  1005. See the PMPRINTF docs for details. I strongly recommend using this utility. 
  1006.  
  1007. IMPORTANT NOTE: If you #define any of the flags at the top of common.h, you 
  1008. must have the PMPRINTF DLLs somewhere on your LIBPATH, or otherwise you'll 
  1009. spend days figuring out why XFolder is simply not working any more. (I had this 
  1010. recently after a reinstall of OS/2, after which the DLLs where gone.) That is, 
  1011. XFolder classes will not load at WPS startup, because the PMPRINTF imports 
  1012. cannot be resolved. Neither will registering XFolder classes succeed. And don't 
  1013. expect to get an error message other than FALSE. :-( 
  1014.  
  1015. _Pmpf(("xxx")) uses regular printf syntax, except for those strange double 
  1016. brackets, which are needed because macros don't accept variable parameter lists 
  1017. otherwise. 
  1018.  
  1019. Take a look at the top of common.h to find out more about the debugging flags. 
  1020.  
  1021.  
  1022. ΓòÉΓòÉΓòÉ 4.16. Making XFolder ΓòÉΓòÉΓòÉ
  1023.  
  1024. If you wish to build the whole XFolder thing including the NLS DLLs and the INF 
  1025. and HLP files, do the following: 
  1026.  
  1027.    1. Put the .EXE files in /TOOLS directory in a directory on your PATH. These 
  1028.       tools are required by the makefiles. 
  1029.  
  1030.    2. In MAKE.CMD in the main directory, you'll have to set a few variables. 
  1031.       This is explained in that file. 
  1032.  
  1033.    3. Call MAKE.CMD, which will recurse into the directories and possibly take 
  1034.       a long time. This will build the main DLL, the NLS DLL, and all the INF 
  1035.       and HLP files. 
  1036.  
  1037.  Note: Depending on whether the XFRELEASE environment variable is set, XFolder 
  1038.  will be compiled with debug code or not. This is determined in 
  1039.  /main/xfldr.mak. If this variable is not defined, you'll get the regular 
  1040.  XFLDR.DLL. If this variable is set to anything, a lot of debug code (including 
  1041.  line information) will be compiled into XFLDR.DLL, making that file more than 
  1042.  1 MB in size. This variable can be set in MAKE.CMD. 
  1043.  
  1044.  Makefiles. Each directory has its own makefile. All makefiles were written for 
  1045.  IBM NMAKE. I don't know if these will work with other make utilities. 
  1046.  
  1047.  /HELPERS no longer has its own makefile, because the sources in here will only 
  1048.  be used by the other XFolder parts, i.e. XFLDR.DLL, TREESIZE.EXE, 
  1049.  NETSCDDE.EXE. The .OBJ files for the helper sources are then created in the 
  1050.  directories of the respective XFolder part, because we might need different 
  1051.  compiler options for each part. 
  1052.  
  1053.  Rebuilding the whole thing. If you want to make sure that all C files are 
  1054.  recompiled, open and save /helpers/dosh.h to make it newer than the target 
  1055.  files. This is #include'd in all XFolder C files, and the makefiles' inference 
  1056.  rules will then enforce recompilation of all C files. 
  1057.  
  1058.  Alternatively, you can use CLEANUP.CMD, which will delete all the produced 
  1059.  files. 
  1060.  
  1061.  
  1062. ΓòÉΓòÉΓòÉ 5. National Language Support (NLS) ΓòÉΓòÉΓòÉ
  1063.  
  1064.      Overview 
  1065.      Requirements for translations 
  1066.      The main NLS DLL (XFLDRxxx.DLL) 
  1067.      The INF and HLP files 
  1068.      The HTML2IPF utility 
  1069.      Images and screenshots 
  1070.      Other files 
  1071.      Testing your NLS files 
  1072.  
  1073.  
  1074. ΓòÉΓòÉΓòÉ 5.1. Overview ΓòÉΓòÉΓòÉ
  1075.  
  1076. Note: If you have already started translating XFolder, please do read the 
  1077. changelog.txt file. There are important changes, or XFolder 0.81 might not run 
  1078. with your NLS files properly. 
  1079.  
  1080. Legal notes. XFolder is placed under the GPL, including the National Language 
  1081. Support (NLS). If you translate the NLS part to your language, you create "a 
  1082. work based on the Program" in the GPL sense. As a result, the GPL automatically 
  1083. applies to your translation too. 
  1084.  
  1085. This means that you have to publish your source code also. 
  1086.  
  1087. Now, to move away from the Legalese, I suggest that you do not distribute 
  1088. XFolder NLS packages yourself. Note that this is not a legal requirement (you 
  1089. may do so if you ship the source code also), but for practical reasons, mainly 
  1090. the following two: 
  1091.  
  1092. For one, all the NLS packages should be available from my homepage for 
  1093. convience. 
  1094.  
  1095. Secondly, since I might update XFolder after you have finished your work on 
  1096. your NLS version, XFolder might have trouble cooperating with your files. 
  1097. Internal IDs might change and/or new features might be added. So if you have 
  1098. finished creating your NLS package, please contact me, and I will put in on my 
  1099. homepage and upload it to the usual places where XFolder is normally available. 
  1100.  
  1101. This seems like the best solution to be, because I have a list of places which 
  1102. carry XFolder, and I can update all the NLS packages myself when anything 
  1103. changes with XFolder. This way, my homepage will always be the place to look 
  1104. for up-to-date NLS packages. 
  1105.  
  1106. Thus, when you're done translating, please zip up the complete directory tree 
  1107. again and mail the ZIP file back to me. 
  1108.  
  1109. How it works. XFolder NLS packages identify themselves to the XFolder core via 
  1110. country codes, as described on the "COUNTRY" page in the OS/2 Command Reference 
  1111. (CMDREF.INF). This package is prepared for creating the English NLS package, as 
  1112. it comes with the default XFolder package. The language code for English is 
  1113. "001". 
  1114.  
  1115. So the first step you'll have to take is finding out your country code. For 
  1116. example, Italian would be 039. 
  1117.  
  1118. Unfortunately, XFolder's National Language Support (NLS) is spread across quite 
  1119. a number of files, which have different file formats. These files are: 
  1120.  
  1121.      The NLS DLL to be put into the XFolder BIN subdirectory. This file 
  1122.       contains the language-dependent stuff which is needed by XFLDR.DLL. 
  1123.       notably dialogs, menus and miscellaneous strings. 
  1124.  
  1125.       The NLS DLL is called XFLDxxx.DLL, with "xxx" being your three-digit 
  1126.       language code. The files neccessary to translate this DLL are in the 001 
  1127.       directory. 
  1128.  
  1129.       See "The main NLS DLL" for details. 
  1130.  
  1131.      The XFolder message file introduced with V0.80 residing in the HELP 
  1132.       subdirectory. This file holds all kinds of messages which are mostly 
  1133.       displayed in XFolder's message boxes and are too large to be put into the 
  1134.       resources of the NLS DLL. This file is called XFLDxxx.MSG, with "xxx" 
  1135.       being your three-digit language code. 
  1136.  
  1137.       The source file for the MSG file is called XFLDRxxx.TXT (in the 001 
  1138.       directory also), with "xxx" being your three-digit language code. 
  1139.  
  1140.       See "The main NLS DLL" for details. 
  1141.  
  1142.      The XFolder Online Reference (INF) in the XFolder main directory. 
  1143.  
  1144.       This file is called XFLDxxx.INF, with "xxx" being your three-digit 
  1145.       language code. The files neccessary to translate this file are in the 
  1146.       001/INF.001 subdirectory. 
  1147.  
  1148.       See "The INF and HLP files" for details. 
  1149.  
  1150.      The XFolder HLP file in the HELP subdirectory. This file holds all the 
  1151.       help panels that are displayed when you press F1. 
  1152.  
  1153.       This file is called XFLDxxx.HLP, with "xxx" being your three-digit 
  1154.       language code. The files neccessary to translate this file are in the 
  1155.       001/HELP.001 subdirectory. 
  1156.  
  1157.       See "The INF and HLP files" for details. 
  1158.  
  1159.      The WPS class descriptions which are displayed on the "WPS Classes" 
  1160.       settings page in the "Workplace Shell" object. This was introduced with 
  1161.       XFolder 0.80 also. 
  1162.  
  1163.       This file is called XFCLSxxx.TXT, with "xxx" being your three-digit 
  1164.       language code. It also resides in the 001 directory. 
  1165.  
  1166.       See "Other files" for details. 
  1167.  
  1168.      A number of REXX .CMD and text files for XFolder's installation. The 
  1169.       files to be translated are in the MISC subdirectory. 
  1170.  
  1171.       See "Other files" for details. 
  1172.  
  1173.      The SmartGuide (Warp 4) script used for the XFolder introduction, which 
  1174.       is displayed right after XFolder has been installed and the WPS has been 
  1175.       restarted. This (XFLDRxxx.SGS) is also in the MISC directory. 
  1176.  
  1177.       See "Other files" for details. 
  1178.  
  1179.  The TOOLS directory contains a valuable tool for converting HTML files to the 
  1180.  IBM (IPF) format. This will be described on a separate page. This directory 
  1181.  also contains a few other needed tools. See the separate README in that 
  1182.  directory. 
  1183.  
  1184.  BTW: I'm really curious how "Snap to grid" sounds in your language. ;-) 
  1185.  
  1186.  
  1187. ΓòÉΓòÉΓòÉ 5.2. Required Tools ΓòÉΓòÉΓòÉ
  1188.  
  1189. Even though all the source files in this package can be edited using any editor 
  1190. (because they're all plain text files), you will need some extra utilities to 
  1191. create the actual NLS files. 
  1192.  
  1193. In any case, a C compiler is not required. 
  1194.  
  1195. To be more precise: 
  1196.  
  1197.      The message file (XFLDxxx.MSG) can only be created if you have any 
  1198.       version of an OS/2 Developer's Toolkit (even 2.x should work), because 
  1199.       you will need MKMSGF.EXE to convert the .TXT file to .MSG format. See 
  1200.       "Other files" for more on this. 
  1201.  
  1202.      The same applies to the .INF and .HLP files: to build these from the .IPF 
  1203.       sources, you will need IPFC.EXE from the Toolkit; see "The INF and HLP 
  1204.       files" for details. 
  1205.  
  1206.      The makefiles in this package were written for IBM NMAKE, which comes 
  1207.       with all the IBM compilers. I'm not sure these will work with other MAKE 
  1208.       utilities. I'd be grateful for feedback. 
  1209.  
  1210.       The makefiles are only for conveniently updating the target NLS files. If 
  1211.       you don't have NMAKE, you have to assemble the files manually. See the 
  1212.       following pages for details. 
  1213.  
  1214.  
  1215. ΓòÉΓòÉΓòÉ 5.3. The NLS DLL ΓòÉΓòÉΓòÉ
  1216.  
  1217. The files in the "001" directory contain everything neccessary to compile a 
  1218. resource DLL (XFLDRxxx.DLL, with xxx being your country code). The resource DLL 
  1219. contains strings, dialogs, and notebook pages. 
  1220.  
  1221. Although the resources are contained in a DLL, the DLL contains no "real" code 
  1222. (except for one dummy function, because every DLL needs to contain at least 
  1223. some code). 
  1224.  
  1225. Necessary preparations. Most files in this directory carry a three-digit 
  1226. language code in their respective names; the files are prepared for English 
  1227. (language code 001). 
  1228.  
  1229.    1. For your language, you need to change all the filenames with "001" in 
  1230.       their names to your country code (e.g. 039 for Italian). 
  1231.  
  1232.    2. You will also have to change the .DEF and .MAK files, which assume a 
  1233.       country code of 001 at this point. Required changes are noted in the 
  1234.       files themselves. 
  1235.  
  1236.  Note that all the dialog ID's access the dlgids.h file in the /MAIN directory. 
  1237.  Do not change anything in that file, or your WPS will behave really funny with 
  1238.  your NLS DLL. If you're lucky, that is. ;-) 
  1239.  
  1240.  Files that need to be changed: 
  1241.  
  1242.      xfldr001.def:The module definition file. Required changes are noted in 
  1243.       the file itself. 
  1244.  
  1245.      xlfdr001.mak: Makefile for IBM NMAKE. Required changes are noted in the 
  1246.       file itself. 
  1247.  
  1248.      xfldr001.rc, xfldr001.dlg: These are the main resource files which need 
  1249.       lots of changes. 
  1250.  
  1251.       I've documented everything you need to change in the .RC file. 
  1252.  
  1253.       The .DLG file is included when the RC files is recompiled. It contains 
  1254.       all the XFolder dialogs (i.e. notebook pages and other dialog windows). 
  1255.       Sorry, there are no comments in there because I'm using DLGEDIT.EXE to 
  1256.       create the dialogs, which rewrites the DLG file at every change, so all 
  1257.       comments in there get lost. 
  1258.  
  1259.      xfldr001.txt: This is the "source" file for the XFLDR001.MSG file. You 
  1260.       will need MKMSGF.EXE from the OS/2 Warp Toolkit to convert this plain 
  1261.       text file into a .MSG file. See the notes in that file. 
  1262.  
  1263.  Using a dialog editor. You can use DLGEDIT.EXE, the IBM dialog editor from the 
  1264.  Developer's Toolkit, to change the dialogs. (This will not affect the .RC 
  1265.  file.) For this, you will need to create the .RES file first (see 
  1266.  "Recompiling" below). 
  1267.  
  1268.  If you then open the .RES file with the dialog editor, you can choose 
  1269.  /main/dlgids.h as an include file so that all the numerical ID's have a more 
  1270.  meaningful name. 
  1271.  
  1272.  When you then save the file, the .RES and .DLG files will be recreated. The 
  1273.  .RC file remains untouched though. 
  1274.  
  1275.  The dialog editor has a helpful "Translate mode" in its "Options" menu which 
  1276.  disables a lot of menu items so you don't accidentally change dlg ID's or 
  1277.  other important stuff. 
  1278.  
  1279.  I don't know if you can use the URE editor also, I have not tried that. 
  1280.  
  1281.  Recompiling the DLL. If you have IBM VAC++, you can simply use MAKE.CMD to 
  1282.  have the DLL recreated. Everything should work fine, since all the neccessary 
  1283.  files are included. 
  1284.  
  1285.  Otherwise, things get a bit more complicated. Since the resource compiler 
  1286.  (RC.EXE) is already included with every OS/2 installation, you can try the 
  1287.  following: 
  1288.  
  1289.    1. Copy an existing XFolder resource DLL into your NLS DLL source directory; 
  1290.       rename it so that it contains your language code. 
  1291.  
  1292.    2. Open a command line in that directory. 
  1293.  
  1294.    3. Type rc xfldr001.rc xfldr001.dll (replace "001" with your language code), 
  1295.       which should create a new .RES file and link it against the existing DLL. 
  1296.  
  1297.  After recompiling, you can test the DLL as described in "Testing the DLL". 
  1298.  
  1299.  
  1300. ΓòÉΓòÉΓòÉ 5.4. The INF and HLP Files ΓòÉΓòÉΓòÉ
  1301.  
  1302. The sources for the INF and HLP files are written using a slightly extended 
  1303. HTML syntax. Creating INF and HLP files is therefore a two-step process: 
  1304.  
  1305.    1. The HTML sources are translated into an .IPF source file, using the 
  1306.       HTML2IPF utility. 
  1307.  
  1308.    2. Next, the .IPF source is fed into IBM's IPFC.EXE from the Developer's 
  1309.       Toolkit. This file is required to produce INF and HLP files, sorry. 
  1310.  
  1311.  Please use the MAKE.CMD file on the top level of the XFolder source files to 
  1312.  have the doc files created. This might take a while. You will first need to 
  1313.  set a few environment variables on top of MAKE.CMD, which is documented in 
  1314.  that file itself. 
  1315.  
  1316.  You then have two alternatives for the translations: 
  1317.  
  1318.      I recommend translating all the .HTML files and keep using MAKE.CMD to 
  1319.       have the HTML files converted into a single .IPF file (using the HTML2IPF 
  1320.       utility), which can then be fed into IPFC.EXE. 
  1321.  
  1322.       This has the advantage that you'll only have to change some panels in 
  1323.       future versions, of which I will keep track. Also, I always note changes 
  1324.       to the INF and HLP files in the HTML source files in HTML comments tags, 
  1325.       so you can easily search for what's changed. 
  1326.  
  1327.       The disadvantage is that, being a REXX program, HTML2IPF is slow. 
  1328.  
  1329.      You can also translate the one .IPF file in each of the INF and HELP 
  1330.       directories directly, if you're familiar with the IPF source language, 
  1331.       which is a proprietary IBM format (and which I don't like at all). 
  1332.  
  1333.       To do this, you'll have to create the two IPF source files first, using 
  1334.       MAKE.CMD. You can then translate this file and feed it into the IPFC.EXE 
  1335.       compiler to have the .INF and .HLP files created. 
  1336.  
  1337.       This has the disadvantage that if certain panels change in future 
  1338.       versions, you'll have no clue what parts changed in this single IPF file, 
  1339.       because the comments about changes are only visible in the HTML sources. 
  1340.  
  1341.       If you still want to use this method, please change the text only. Do not 
  1342.       change any resources, IPF tags, and especially not the resource ID's, or 
  1343.       XFolder will not find its help panels any more. 
  1344.  
  1345.  The "root" file in each of the two source directories is called XFLDRxxx.HTML, 
  1346.  respectively, with "xxx" being your country code (which you should change in 
  1347.  this one filename because HTML2IPF will use this name for the target IPF file 
  1348.  also). 
  1349.  
  1350.  To use HTML2IPF manually (instead of through MAKE.CMD), open a command line in 
  1351.  the INF or HLP directory (with XFolder ;-) ), and type: 
  1352.  
  1353.  <path>\html2ipf xfldr001.html 
  1354.  
  1355.  This will create a XFLDRxxx.IPF file (in the above example, XFLDR001.IPF). You 
  1356.  can then run ipfc XFLDRxxx.IPF to compile a HLP file; add an /INF switch to 
  1357.  produce an "INF" file. You must have the INF or HLP directory as your current 
  1358.  directory, or HTML2IPF will tumble. 
  1359.  
  1360.  If you don't have the Developer's Toolkit, there's no way you can actually 
  1361.  produce the INF and HLP files. You will have to use Netscape or WebExplorer to 
  1362.  view the help files, which of course are on many separate pages then. Begin 
  1363.  viewing XFLDRxxx.HTML in the INF and HELP directories, respectively. 
  1364.  
  1365.  In any case, mind these important notes: 
  1366.  
  1367.      The (slightly awkward, I admit) structure of the files is the following, 
  1368.       in both directories: 
  1369.  
  1370.      XFLDRxxx.HTML is the "root" file. Files beginning with "0" appear in the 
  1371.       contents tree of the produced INF and HLP files. All other files are 
  1372.       somwhere below in the INF/HLP table-of-contents hierarchy, depending on 
  1373.       the SUBLINKS tags in the HTML source files. 
  1374.  
  1375.      Do not change filenames! HTML2IPF sorts the IPF pages internally 
  1376.       alphabetically according to the filenames, that's why I've implemented 
  1377.       these strange naming conventions. I admit that since the structure has 
  1378.       developed over time, it may not seem very logical to you, but it works. 
  1379.       Changing things here will result in a lot of work, since all the links in 
  1380.       the HTML files will have to be renamed also. 
  1381.  
  1382.       Also, if you change the linkage of the HTML files, the resource IDs of 
  1383.       the help panels will be altered, and XFolder will then get confused 
  1384.       displaying the proper help panels. 
  1385.  
  1386.      Within the HTML files, do not change anything within angle brackets 
  1387.       ("<xxx>"). Translate only the text outside of these. Even though some 
  1388.       tags might not be good HTML style and the HTML files might not look 
  1389.       pretty when viewed with Netscape, certain tag combinations (especially 
  1390.       the <BR><LI> combinations) are neccessary to make the pages look good for 
  1391.       IPF. 
  1392.  
  1393.      Don't forget to translate the page titles (in between the <TITLE> tags). 
  1394.       This is what appears in the title of a panel window and in the "Table of 
  1395.       contents" tree. I've forgotten this many times... 
  1396.  
  1397.      There are a number of files in the HLP directory which seem pretty 
  1398.       useless. These are neccessary however in order to guarantee a certain 
  1399.       sequence of the help panels in the resulting HLP file, on which XFolder 
  1400.       relies for calling a certain help panel. I don't quite understand myself 
  1401.       anymore how this order works, but it does, so I don't care. ;-) 
  1402.  
  1403.      I do not recommend translating everything for the INF book. I have done 
  1404.       the German translation myself, and I think that the "Revision history" 
  1405.       section makes no sense translating, because it is frequently updated and 
  1406.       NLS versions didn't exist for the older versions anyway. Also, the 
  1407.       "XFolder Internals" pages apply to programmers, which need to know 
  1408.       English anyway, because otherwise they won't find their way through the 
  1409.       required Toolkit docs either. So I think you can save yourself some work 
  1410.       there. 
  1411.  
  1412.  
  1413. ΓòÉΓòÉΓòÉ 5.5. The HTML2IPF Utility ΓòÉΓòÉΓòÉ
  1414.  
  1415. The TOOLS directory contains the very valuable HTML2IPF tool by Andrew Pavel 
  1416. Zabolotny. This REXX script is capable of creating a single .IPF file from a 
  1417. list of linked HTML files, which can then be passed to IBM's IPFC.EXE for 
  1418. creating .HLP and .INF  files. 
  1419.  
  1420. I have slightly modified this tool (see notes below). 
  1421.  
  1422. Even if you don't know what I'm talking about, in this directory, you need to 
  1423. open HTML2IPF.CMD and change three, maybe four things: 
  1424.  
  1425.      In line 27, translate the Resources on the Internet string. 
  1426.      In lines 28-31, translate the string beginning with This chapter 
  1427.       contains... translate every line, but do not mess with the '||'0d0a'x 
  1428.       codes and such. 
  1429.      In lines 34/35 translate the Click below to launch [code] with this URL: 
  1430.       string, but do not change the code in the middle. 
  1431.      In line 20, change the image converter; this is thoroughly explained in 
  1432.       the Images section. 
  1433.  
  1434.  Additional information (not obligatory) 
  1435.  
  1436.  I have included HTML2IPF.INF, which describes how the tool works. You need not 
  1437.  bother with this though, because everything is already set up properly. 
  1438.  
  1439.  I have changed HTML2IPF.CMD in a few places to allow for IPF window 
  1440.  positioning and certain extra character formatting. These changes are only 
  1441.  documented here, in case you're interested -- you will NOT find these changes 
  1442.  in the INF file (you don't have to know this, just if you're curious): 
  1443.  
  1444.      The <HTML> tag has new attributes: XPOS= and YPOS= work just like IPF's 
  1445.       "x" and "y" tags; WIDTH= and HEIGHT are the same as in IPF. 
  1446.      Added the strings described above to global variables for NLS. 
  1447.      The <A> tag accepts a new "AUTO=" attribute, which works just like 
  1448.       "HREF=", but automatically opens and closes the window (this is, for 
  1449.       example, used on the "Introduction" page of the XFolder Online 
  1450.       Reference). 
  1451.      The <CITE> and </CITE> formatting tags are now set to use a 
  1452.       non-proportional font, which is used extensively. 
  1453.      Some formatting changes (<UL>, <BR>, <B> etc.). 
  1454.      HTML2IPF now removes indenting spaces at the beginning of lines because 
  1455.       these would all appear in the INF/HLP files, while HTML ignores them. 
  1456.       (New with V0.81). 
  1457.  
  1458.  
  1459. ΓòÉΓòÉΓòÉ 5.6. Images and Screenshots ΓòÉΓòÉΓòÉ
  1460.  
  1461. The images in both the INF and HELP directory are always available in both GIF 
  1462. and uncompressed OS/2 1.3 BMP format. The reason for this is that HTML does not 
  1463. support BMP, and IPF does not support GIF. :-( 
  1464.  
  1465. HTML2IPF is very comfortable in this respect: it will automatically convert all 
  1466. GIF images to BMP format every time it finds an <IMG> tag, but only if no BMP 
  1467. file of the same filestem was found (see HTML2IPF.INF for details). 
  1468.  
  1469. The image conversion program which HTML2IPF requires is specified in line 20 of 
  1470. HTML2IPF.CMD. The original had Image Alchemy in here, I have changed it to 
  1471. "GBMSIZE", which is part of the freeware "Generalized Bitmap Module" (GBM) 
  1472. package available at Hobbes. 
  1473.  
  1474.      If you don't have GBMSIZE on your PATH, you can add the path to this 
  1475.       line. 
  1476.  
  1477.      If you wish to use a different converter, specify it here. Be careful 
  1478.       though: IPFC only supports uncompressed OS/2 1.3 bitmaps (see 
  1479.       HTML2IPF.INF). That is, neither compressed bitmaps nor Windows or OS/2 
  1480.       2.0 bitmaps work. This is annoying, because IPFC's own image compression 
  1481.       is totally outdated, but there's nothing we can do about this. 
  1482.  
  1483.  I'd be very grateful if you could create your own screenshots for the online 
  1484.  documentation, because I own German versions of OS/2 and for your NLS package, 
  1485.  screenshots of your language are preferrable, at least for those pictures 
  1486.  which have language-dependent stuff in them. 
  1487.  
  1488.  I have used the following settings for the screenshots (just for your 
  1489.  information, you don't have to use these): 
  1490.  
  1491.   Fonts used:
  1492.   Titlebars: Humanist 521, 13 points (available on the
  1493.              CorelDraw 4 CD in Type 1 format)
  1494.   All the other fonts are set to 9.WarpSans.
  1495.   CandyBarZ installed, colors:
  1496.   Active:     top 191/0/0, bottom 52/0/0
  1497.   Inactive:   top 160/160/130, bottom 40/40/40
  1498.   Oh yes, XFolder installed. ;-)
  1499.  
  1500.  Now, if you create your own screenshots, save them as GIFs with the exact 
  1501.  filenames of the originals (e.g. trunc.gif); you must then DELETE the 
  1502.  respective BMP file, because HTML2IPF will only call the image converter for 
  1503.  BMP if no BMP file of the same name exists. 
  1504.  
  1505.  Tricks to reduce file sizes: 
  1506.  
  1507.  Keep in mind that HLP/INF files have their own compression scheme which works 
  1508.  best when much redundant data is in the bitmap files. That is, large areas of 
  1509.  a plain color can be compressed best. 
  1510.  
  1511.  So taking screenshots of folders with background bitmaps is a no-no, because 
  1512.  this will really blow up the files. 
  1513.  
  1514.  And use as few colors as possible. You can use PMView to reduce the number of 
  1515.  colors to, say, 12 colors, which usually still looks alright. Make sure you 
  1516.  don't have "dithering" or "error diffusion" enabled, because this will add 
  1517.  lots of extra pixels which will make compression less efficient. 
  1518.  
  1519.  Also, if you need to scale images to a smaller size, make sure not to enable 
  1520.  any "interpolation", i.e. introducing extra pixels to make colors smoother. 
  1521.  This adds lots more colors to the file, which cannot be compressed well. 
  1522.  
  1523.  
  1524. ΓòÉΓòÉΓòÉ 5.7. Directory "MISC" ΓòÉΓòÉΓòÉ
  1525.  
  1526. The MISC directory contains files used by XFolder's installation script 
  1527. (INSTALL.CMD) plus the SmartGuide Script used for the XFolder introduction. 
  1528.  
  1529.      INSTxxx.MSG (with "xxx" being your country code, which you need to 
  1530.       change) is -- I'm sorry -- in a proprietary format. It's not difficult to 
  1531.       understand though: The file is used by XHELP.CMD (in the XFolder 
  1532.       package), which is capable of extracting single text messages in between 
  1533.       the <TOPIC>; and </TOPIC> tags in this file. The text between these tags 
  1534.       is then displayed on the screen. 
  1535.  
  1536.       Please note that this file will disappear in a future release of XFolder, 
  1537.       as soon as the WarpIn installer is functioning, which I am currently 
  1538.       working on. See my WWW homepage for details. 
  1539.  
  1540.       If you still wish to translate this file, what you need to do here is 
  1541.       simply translate all the text which follows a <TOPIC> tag. The text is 
  1542.       displayed "as is", and no formatting is performed; as a result, you must 
  1543.       take care that no more than 80 characters are contained in a line. 
  1544.  
  1545.       You also should take care of the line breaks: it makes a difference in 
  1546.       output whether a </TOPIC> end tag is found at the end of a line or at the 
  1547.       beginning of a new line, because in the latter case, the line break is 
  1548.       still printed to the screen. 
  1549.  
  1550.       Just one more note: Do not change the keys mentioned in this file ("X", 
  1551.       "Y", "N"), even if your language does not use "Y" for saying "Yes". 
  1552.       Unfortunately, INSTALL.CMD relies on these keys. :-( 
  1553.  
  1554.      CROBJxxx.CMD is a straightforward REXX script which creates the default 
  1555.       XFolder Configuration Folder. Even if you don't know REXX, don't worry: 
  1556.       you only have to change the strings on top of the file, which contain all 
  1557.       the language-dependent things. Be careful with the quotes. Do not change 
  1558.       anything else, because XFolder relies on it. 
  1559.  
  1560.      SOUNDxxx.CMD is the REXX script which creates the neccessary INI entries 
  1561.       for having the new XFolder system sounds in your "Sound" object. Only 
  1562.       change the strings at the top of the file to your language. 
  1563.  
  1564.      XFLDRxxx.SGS is a Warp 4 SmartGuide script to display the "Welcome" 
  1565.       window after XFolder has been installed and the WPS has been restarted. 
  1566.  
  1567.       I have no idea what the precise syntax for these files is (once again has 
  1568.       IBM developed good software, but then lets it rot), but it seems to be 
  1569.       some HTML-like syntax, except that the tags MUST be in lower case, or 
  1570.       they won't work. 
  1571.  
  1572.  
  1573. ΓòÉΓòÉΓòÉ 5.8. Testing Your NLS Files ΓòÉΓòÉΓòÉ
  1574.  
  1575. XFolder's NLS depends entirely on a single entry in OS2.INI 
  1576. ("XFolder"::"LanguageCode"). This entry defaults to a "001" string and can be 
  1577. changed either at installation time (if the install script does it) or by using 
  1578. the "Language" setting in the "Workplace Shell" object, "XFolder" page 2. 
  1579.  
  1580. All NLS resources are loaded depending on this one setting. That is, if you 
  1581. change the language, XFolder expects not only your NLS DLL to be present in 
  1582. /BIN, but also the MSG, HLP, and WPS class description files in /HELP. So if 
  1583. you have not translated these yet, you might want to create a copy of the 
  1584. English ones with your language code in the filename. 
  1585.  
  1586. To test a new version of your NLS files: 
  1587.  
  1588.      Make sure you do not currently have your new NLS DLL selected on the 
  1589.       "XFolder Internals" settings page, because if you do, the DLL is locked 
  1590.       by XFolder and cannot be replaced. 
  1591.  
  1592.       Select "US English" instead, which will unlock the previously used DLL, 
  1593.       which can then be deleted from the XFolder directory. 
  1594.  
  1595.       Then put your new DLL into the BIN subdirectory and open the settings 
  1596.       again; select your DLL and see if things work. 
  1597.  
  1598.      Additional caveat for INF/HLP files: Before compiling the .IPF to the 
  1599.       .HLP/.INF files, you should make sure that the target file is not 
  1600.       currently in use. 
  1601.  
  1602.       With INF files, that's easy: simply close it if it's open. 
  1603.  
  1604.       With HLP files, you have to keep in mind that the WPS keeps these files 
  1605.       locked even after you've closed a help panel window. However, the WPS 
  1606.       only ever keeps a single HLP file locked at a time, so in order to unlock 
  1607.       the XFolder HLP file, simply open a default WPS help panel, e.g. by 
  1608.       selecting "Extended Help" for the Desktop window. 
  1609.  
  1610.       You can then copy the new XFolder .HLP file to the XFolder HELP 
  1611.       directory. (MAKE.CMD will do this automatically.) 
  1612.  
  1613.  
  1614. ΓòÉΓòÉΓòÉ 6. Resources on the Internet ΓòÉΓòÉΓòÉ
  1615.  
  1616. This chapter contains all external links referenced in this book.  Each link 
  1617. contained herein is an Unified Resource Locator (URL) to a certain location  on 
  1618. the Internet. Simply double-click on one of them to launch Netscape  with the 
  1619. respective URL. 
  1620.  
  1621.  
  1622. ΓòÉΓòÉΓòÉ 6.1. http://www.edm2.com ΓòÉΓòÉΓòÉ
  1623.  
  1624.                   Click below to launch Netscape with this URL:
  1625.  
  1626.                                http://www.edm2.com
  1627.  
  1628.  
  1629. ΓòÉΓòÉΓòÉ 6.2. http://www.ozemail.com.au/~dbareis/ ΓòÉΓòÉΓòÉ
  1630.  
  1631.                   Click below to launch Netscape with this URL:
  1632.  
  1633.                        http://www.ozemail.com.au/~dbareis/
  1634.  
  1635.  
  1636. ΓòÉΓòÉΓòÉ 6.3. http://www2.rz.hu-berlin.de/~h0444vnd/os2.htm ΓòÉΓòÉΓòÉ
  1637.  
  1638.                   Click below to launch Netscape with this URL:
  1639.  
  1640.                   http://www2.rz.hu-berlin.de/~h0444vnd/os2.htm
  1641.  
  1642.  
  1643. ΓòÉΓòÉΓòÉ 6.4. mailto:ulrich.moeller@rz.hu-berlin.de ΓòÉΓòÉΓòÉ
  1644.  
  1645.                   Click below to launch Netscape with this URL:
  1646.  
  1647.                       mailto:ulrich.moeller@rz.hu-berlin.de
  1648.  
  1649.  
  1650. ΓòÉΓòÉΓòÉ 6.5. notices_3comments.html ΓòÉΓòÉΓòÉ
  1651.  
  1652.                   Click below to launch Netscape with this URL:
  1653.  
  1654.                              notices_3comments.html
  1655.