home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: WPS_PM
/
WPS_PM.zip
/
xfld085s.zip
/
progref.inf
(
.txt
)
< prev
next >
Wrap
OS/2 Help File
|
1999-03-15
|
68KB
|
1,655 lines
ΓòÉΓòÉΓòÉ 1. XFolder Programmer's Guide and Reference ΓòÉΓòÉΓòÉ
Notices
Introduction -- start here
National Language Support
The XFolder source code
ΓòÉΓòÉΓòÉ 2. Notices and Legalese ΓòÉΓòÉΓòÉ
Licence (CHANGED!)
GNU Public Licence
Please see the XFolder Online Reference for more notices.
ΓòÉΓòÉΓòÉ 2.1. Licence And Disclaimer ΓòÉΓòÉΓòÉ
March 1999
While previous XFolder versions were "plain" freeware, all XFolder versions
since V0.80 have been placed under the GNU General Public Licence (GPL) Version
2.
You can find the full text of the GPL in the plain-text file COPYING in the
XFolder installation directory. I have added a formatted version of this on the
next page of this document.
By installing XFolder on your system, you declare your agreement to the terms
and conditions of the GNU General Public Licence, Version 2, as contained in
the file COPYING in the XFolder installation directory.
The GPL means more Legalese, but also more rights for you as a user and, if
applicable, developer. The most obvious change is that XFolder's source code is
now also released.
The following brief explanations are intended as an introduction to the terms
and conditions of the GPL only. They are not part of the licence agreement, for
which only the terms and conditions in the COPYING file shall prevail.
If you are an XFolder user, not much has changed. You may still use
XFolder without any payment to Ulrich MФller. The GPL does not restrict
you on this matter, because it only imposes restrictions on distribution
and modification of software. However, there is still no warranty
whatsoever. If XFolder ruins your system and your work of the last 30
years is lost, sorry. (This is not very probable though). Refer to the
bottom of the GPL for the detailed disclaimer.
If you're a distributor, you may still distribute the whole XFolder
package. However, the GPL will probably require you to also distribute
the complete XFolder source code, which is available in a separate
package from the author's WWW homepage. Refer to the GPL for details.
If you're a developer, you now have the source code, which you may use
and modify. However, if you base your own software on XFolder's source
code, the GPL will most probably require you to place your work under the
GPL also. This means that you cannot use my sources if you don't publish
all your sources also.
Even though I'm publishing the source code, I retain the copyright to
what I've written.
The GPL deals with these issues extensively. Before you use or modify any
code parts of XFolder, make sure you read the GPL thoroughly. If your
software is GPL'd also, by all means feel free to use my code. If you
have any questions, feel free to contact me.
This licence does not necessarily cover future releases. Ulrich MФller retains
the right to modify the licence agreement for future versions.
And now: have fun with XFolder!
(C) Copyright 1997-99 Ulrich MФller.
ΓòÉΓòÉΓòÉ 2.2. GNU Public Licence ΓòÉΓòÉΓòÉ
For a formatted version of the GPL, check the XFolder Online Reference
("Notices" section).
ΓòÉΓòÉΓòÉ 3. Introduction -- Start Here ΓòÉΓòÉΓòÉ
Welcome to the XFolder source code!
Changes made since the initial source code release (which was for V0.80) are
logged in the changelog.txt file in the root directory of the source package. I
hope this is fairly complete.
You must unzip this package on a HPFS drive because many files in this package
contain long file names.
This file covers two different things:
1. Information about the XFolder C source code. This is mainly of interest
for programmers who would like to contribute to XFolder, find bugs, or
who are just interested in learning how the thing is functioning.
Some more legalese: BEFORE USING OR MODIFYING ANY CODE, MAKE SURE YOU
READ THE GNU GENERAL Public LICENCE IN ITS ENTIRETY.
If I find out that you steal from me without complying to the GPL, you'll
get into trouble. I am not releasing XFolder's source code to make it
easier for shareware or commercial developers to sell better software,
but to get freeware programmers to write WPS classes.
However, if you follow the GPL, you are strongly encouraged to use any of
my code. After all, I am also using public code. OS/2 needs more
freeware!
If you have questions regarding licence issues, please contact me.
2. Information about XFolder National Language Support (NLS). This is of
interest for people who would like to translate XFolder only. No
knowledge of C programming is required for this.
See the "NLS Overview" page for more information.
If you have questions, feel free to contact me at
ulrich.moeller@rz.hu-berlin.de.
But if you want to start writing WPS classes, please don't start asking me
things like "What is an IDL file?". If you have never created a WPS class,
please read the excellent courses at EDM/2 (www.edm2.com) first, which explain
a lot of things to get you started. As far as I know, XFolder is the most
complex WPS source code available, and it probably does not serve very well as
a WPS beginner's tutorial.
Thanks!
ΓòÉΓòÉΓòÉ 4. The XFolder Source Code ΓòÉΓòÉΓòÉ
Overview
Requirements for compiling
The /MAIN directory
The /HELPERS directory
XFolder function prefixes
Some SOM tricks
XFolder settings
Folder window subclassing
Menu manipulation
Extended sort functions
XFolder threads
Playing Sounds
XShutdown
XFolder Exception Handling
Debugging XFolder
Making XFolder
ΓòÉΓòÉΓòÉ 4.1. Overview ΓòÉΓòÉΓòÉ
Before going into the details of source code, which is complex enough to get
even the more experienced programmer confused, please read the chapters in the
"XFolder internals" chapter of the XFolder Online reference for a first
introduction to XFolder's basic inner workings.
This will give you a vague idea of what XFolder is doing where and deals with
the most important concepts only, so you don't get overwhelmed by all the
details which come in this file.
The different subdirectories contain the different parts of XFolder.
The /001 directory tree contains all the National Language Support (NLS)
for English.
The MAIN directory contains the XFolder main DLL (XFLDR.DLL) files, which
is composed from all the .C sources. These in turn contain all the
SOM/WPS classes and some library functions. This DLL loads the NLS DLL
(XFLDRxxx.DLL, with xxx being a language code) at WPS bootup or when the
language is changed using the "XFolder Internals" settings page. See this
page for more.
The /HELPERS subdirectory contains a lot of C files with helper functions
which are independent of XFolder. That is, these can be used with any
OS/2 VIO and/or PM program. The functions are grouped into categories.
See this page for more.
The HELPERS dir also contains files from Dennis Bareis' PMPRINTF package,
which is available in full from his homepage. Refer to the "Debugging
XFolder" section for details.
The /NETSCDDE subdirectory contains the source code of the Netscape DDE
interface and the INF sources. This is pretty straightforward, aside from
the messy DDE stuff, which is only half documented, both by IBM and
Netscape.
The /TREESIZE subdirectory contains the source code of the external
TREESIZE utility, which is called if you select "Treesize" from a
folder's context menu (new with V0.81).
This might be quite useful to you if you're interested in learning some
PM container programming, which I've only begun to understand while
developing this utility. This also shows some techniques of how to
multithread PM programs without blocking the system, which is not
trivial.
/WPSRESET, /REPCLASS and /XSHUTDWN contain the sources of the little
XFolder utilities of the same name. These are described in the "Related
Files" section of the XFolder Online Reference.
/TOOLS contains some tools used by the makefiles. Put these on your PATH
before making XFolder.
ΓòÉΓòÉΓòÉ 4.2. Required Tools ΓòÉΓòÉΓòÉ
Compiler. With V0.80, I have switched to IBM VisualAge C++ 3.0 to develop
XFolder. I have not tried EMX/GCC because I'm too lazy to get used to it,
even though it might compile faster.
I'm not perfectly sure whether I'm using IBM-specific language
extensions. I had to switch the language level to "extended" to use some
none-POSIX C stuff, and I'm not sure whether this is working with GCC. I
have looked up some functions in the EMX docs, such as _beginthread, and
these appear to be the same, even though they're not POSIX C.
If you get these sources compiled with a different compiler, please let
me know or supply patches.
Whatever compiler you use, you need some OS/2 Developer's Toolkit for all
the SOM header files.
The Warp 3 toolkit is sufficient. XFolder does some tricks for Warp 4
too, but does it even though I don't have the Warp 4 toolkit. ;-) The
Toolkit is also needed for changing NLS files, even though you won't need
a compiler for that.
All the .C files have lots of debugging code which can conditionally be
compiled using certain #define's in common.h.
Only if you enable the debugging code, you need the full PMPRINTF package
by Dennis Bareis. You do _not_ need that package if you don't use the
debugging #define's (which is the default), so don't worry.
Check the "Debugging" section of this README for details.
Also see the "Making XFolder" section for how to rebuild XFolder.
ΓòÉΓòÉΓòÉ 4.3. The /MAIN directory ΓòÉΓòÉΓòÉ
The code for the XFolder main DLL (XFLDR.DLL) is in /MAIN. It uses a lot of
code from the /HELPERS directory, which is new with V0.81 and contains all the
helpers code which could also be used independently of XFolder. See the next
page for more.
The XFolder package contains many classes, but puts them all into a single DLL.
This is possible by specifying the same target DLL in the IDL files. One can
put several classes into one .IDL file (which happens in xfldr.idl for example)
or spread them across several IDL files too.
Note that the .DEF files are not used, except for one. These files are created
automatically by the SOM compiler, which cannot however create a single DEF
file if you use several IDL files for the same DLL. So I created xfjoint.def
manually, which is used instead for linking. This file exports lots of
mysterious SOM structures which allow the SOM kernel see the classes in the
DLL.
The filenames with xf* contain the XFolder WPS classes. The filenames are
similar to the original WPS header files for the classes which are replaced by
the XFolder classes.
Here is a short overview. Some of the XFolder concepts are then laid out in
more detail below:
xfdataf.* is for XFldDataFile.
xfdesk.* is for XFldDesktop only. With V0.84, lots of code has been moved
to separate files from this file.
xfdisk.* is for XFldDisk. This just maps a lot of context menu features
to the XFolder routines.
xfldr.* is for the XFolder (WPFolder replacement) class, probably the
main part of XFolder. This also has the subclassed folder frame window
procedure with all the bells and whistles. See "Folder window
subclassing" for details.
This also contains XfldStartup and and XFldShutdown folders, which are
plain subclasses of XFolder.
xfobj.* is for XFldObject, which is needed to get access to some WPS
internals and initialize the XFolder environment.
xfpgmf.* (new with V0.84) is for XFldProgramFile, which does the icon
replacements for executable files.
xfsys.* used to be XFldSystem, now (V0.80) contains the two classes
derived from WPSystem, i.e. XFldWPS and XFldSystem (for the "Workplace
Shell" and "OS/2 Kernel" objects, respectively). This contains most of
the code for the notebook pages.
Common header files:
dlgids.h contains all the dialog id's which are used by both the NLS
resource DLLs and the XFolder main DLL.
DO NOT MESS WITH THIS FILE OR EVERYTHING WILL BLOW UP. This file has
grown since the end of 1997 and is not very logical any more.
common.h contains both the funcs from common.c as well as lots of
#define's which are _not_ used by the NLS DLLs to avoid having to
recompile them all the time. I have done a lot of cleanup with the
common.* files with V0.84.
Other files:
apm.* contains the APM power-off code, thanks to ARAKAWA Atsushi, who
filled this in (V0.82) (apm* function prefix).
classlst.* "WPS Classes" dialog and SOM logic (used to be objdlgs.* in
V0.80) (cls* function prefix). See "Some SOM Tricks" for details.
cnrsort.* contains sort functions for container sorting only (used to be
xfsort.* in V0.80). See "Extended sort functions" for details.
common.* contains lots of miscellaneous functions which are used by all
parts of XFolder (cmn* function prefix), mostly to deal with XFolder
Global Settings and other stuff which is independent of the SOM classes.
except.* (new with V0.84) contains the XFolder exception handlers which
used to be in xfdesk.c (exc* function prefix). See "XFolder exception
handling" for details.
menus.* (new with V0.81) contains all the menu logic which was previously
in the xfldr.c file (mnu* function prefix). See "Menu manipulation" for
details.
module.* contains XFolder's _DLL_InitModule function and some more
functions to query information about the XFolder DLL (mod* function
prefix).
notebook.* (new with V0.82) contains very useful notebook helper
functions, which save me from having to rewrite the same window
procedures for every single notebook page. Almost all XFolder notebook
pages now use these routines (ntb* function prefix).
statbars.* (new with V0.81) status bar logic, previously spread across
many files (stb* function prefix).
xshutdwn.* (new with V0.84) now contains all the XShutdown code which
used to be in xfdesk.c (xsd* function prefix). See "XShutdown" for
details.
xthreads.c.* (new with V0.84) now contains the Worker and Quick threads,
which also used to be in xfdesk.c (xthr* function prefix). See "XFolder
threads" for details.
xwps.c.* (new with V0.84) now contains all kinds of pseudo SOM functions
which used to carry the cmn* prefix, but were spread all over the place
and thus hard to find. All these functions have been put into this file
and given the xwps* prefix. See "Some SOM Tricks" for details.
And then there's SOUND.DLL, which is compiled from the sound.* files (snd*
function prefix; see the "Sounds" section).
ΓòÉΓòÉΓòÉ 4.4. The /HELPERS directory ΓòÉΓòÉΓòÉ
animate.* contains helper functions to animate icons and also other
animation funcs.
dosh.* Control Program helper functions.
eas.* contains helper functions to handle extended attributes.
gpih.* GPI (graphics) helper functions.
linklist.* contains helper functions to handle linked lists.
procstat.* modified Kai Uwe Rommel's DosQProc() functions.
progbars.* progress bar code.
prfh.* contains profile (INI) helper functions.
stringh.* contains helper functions to handle strings/texts
shapewin.* contains the ShapeWindows library. See the top of shapewin.c
for details (new with V0.85).
threads.* contains helper functions to synchronize threads.
winh.* Win (PM) helper functions.
wphandle.* Henk Kelder's WPS handles functions (thanks again, Henk!)
prfh.* is new with V0.82 and contains Profile (INI) helper functions.
ΓòÉΓòÉΓòÉ 4.5. XFolder Function Prefixes ΓòÉΓòÉΓòÉ
With V0.81, I have rearranged a lot of files across many more files to make a
bit clearer where the different functions reside. I guess nobody was able to
overlook what was going on where.
In addition, I have renamed many functions, giving them prefixes which show in
which file they reside:
anm* /helpers/animate.*
apm* /main/apm.*
cmn* are now (V0.84) exclusively in /main/common.c.
dosh* /helpers/dosh.*
ea* /helpers/eas.*
exc* /main/except.* (new with V0.84)
gpih* /helpers/gpih.*
lst* /helpers/linklist.*
mnu* /main/menus.*
mod* /main/module.*
pbar* /helpers/progbar.*
prfh* /helpers/prfh.* (new with V0.82)
prc* /helpers/procstat.*
shp* /helpers/shapewin.c (new with V0.85)
stb* /main/statbars.*
strh* /helpers/stringh.*
thr* /helpers/threads.*
wph* /helpers/wphandle.*
xsd* /main/xshutdwn.* (new with V0.84)
xthr* /main/xthreads.* (new with V0.84)
xwps* /main/xwps.* (new with V0.84)
xf* SOM instance methods in the /main/xf* files
xfcls* SOM class methods in the /main/xf* files
ΓòÉΓòÉΓòÉ 4.6. Some SOM Tricks ΓòÉΓòÉΓòÉ
In general, XFolder is pretty straightforward SOM/WPS code. It overrides a lot
of wp* and wpcls* methods.
In order to avoid too much confusion, the methods which XFolder adds do not
carry the usual wp* and wpcls* prefixes, but xf* and xfcls* instead. Only
XFolder SOM methods have this prefix; "normal" functions have other prefixes.
As XFolder became more complex over time, I have delved quite deeply into SOM.
While I still don't fully understand what is going on in the SOM kernel (from
what I hear, I guess nobody does) and some bugs in there keep puzzling me, but
I've found out some interesting stuff.
Most of this is related to the "WPS Classes" page in the new "Workplace Shell"
object (xfsys.*). The SOM logic for this is in classlst.c in clsWPSClasses2Cnr,
which can analyze the current SOM runtime environment (which is that of the
WPS), i.e. all the classes that have been loaded and query their inheritance
hierarchy at runtime.
This inserts the WPS class tree as recordcores into a given cnr control. This
works with any containers in tree views, so that some XFolder dialogs can use
this too. Check the sources, there's some interesting stuff.
Note that there are quite a number of functions in XFolder which take SOM (WPS)
objects as a parameter, even though they are not SOM methods. See xwps.c for
examples. The reason for this is that resolving SOM methods takes quite a bit
of time, and calling regular functions will work just as well, but faster.
If you look into the .IH header files created by the SOM compiler, you see that
the C bindings for method calls are really all macros #define'd in the header
files which translate into more complex C code.
Here's an example: if you call _wpQueryStyle(somSelf) in xfldr.c, where this
method has not been overridden, the WPObject version of this method should get
called. Here's the #define in xfldr.ih for this:
#define XFolder_wpQueryStyle WPObject_wpQueryStyle
And WPObject_wpQueryStyle is #define'd in wpobject.h from the toolkit headers
as follows:
#define WPObject_wpQueryStyle(somSelf) \
(SOM_Resolve(somSelf, WPObject, wpQueryStyle) \
(somSelf))
Actually, there are more macros related to this, but this is the important one.
SOM_Resolve in turn is a macro #define'd in somcdev.h, which calls the SOM
kernel function somResolve. That function finally goes through the class method
tables to find the actual function address and call it.
As as result, not only does compiling of SOM code take ages (because of all the
nested macros), but also calling SOM methods does, because as opposed to
"static" OO languages such as C++, method resolution is occuring at run-time.
IBM says in the SOM docs that calling a SOM method takes at least three times
as long as calling a normal C function.
Since there is no real need to write functions as SOM methods, except when you
want to design a method which can be overriden in subclasses, I have only done
so in rare occasions to speed up processing.
Here are some other SOM tricks and functions which are not mentioned directly
in the WPS reference (but only in the chaotic SOM docs), but these are very
useful and should be known to everyone:
Since all the SOM stuff is declared in those huge header files, you need
to #include a header file if you need access to certain class-specific
features.
For example, if you write a subclass of WPDataFile and need some
program-object method call (e.g. _wpQueryProgDetails), you need to put
#include <wppgm.h> on top of your code, or the method binding will not be
found.
This is not neccessary if the method is defined for a superclass of your
class, because the SOM headers automatically #include all the parent
classes. That is, for example, you don't need to #include wpfsys.h (for
WPFileSystem) for your WPDataFile subclass.
The most important thing to keep in mind is that all SOM classes are
objects too. They are instances of their respective metaclasses. This
takes some getting used to, but it is this concept only which allows WPS
classes to be created at runtime and for class replacements in the first
place.
That is, for example, any WPS object is an instance of WPObject (really
one of its subclasses). The WPObject class in turn is an instance of its
metaclass, M_WPObject. The WPObject class has a so-called "class object"
at runtime, the metaclass does not.
For any existing class you always have a corresponding macro which is an
underscore plus the class name. That is, the class object of WPObject can
always be obtained with _WPObject.
BOOL _somIsA(pObject, pClassObject) checks for whether pObject is an
instance of the class specified by pClassObject or one of its subclasses.
This is extensively used in statbars.c to adjust status bar display.
Example: _somIsA(somSelf, _WPObject) should always be true within the WPS
context, since all WPS classes are subclasses of WPObject.
PSZ _somGetName(pClassObject) returns the actual name of the class
specified by pClassObject, as specified in the IDL file. (That is
different from wpclsQueryTitle.)
Example: _somGetName(_XFldObject) will return "XFldObject".
SOMClass* _somGetParent(pClassObject) returns a parent class.
Examples: _somGetParent(_WPProgram) returns the WPAbstract class object
(_WPAbstract). _somGetParent(_XFolder) should return _WPFolder, unless
there's some other WPFolder replacement class above XFolder in the
replacement list.
BOOL _somDescendedFrom(pClass, pClassParent) returns true if pClass is
descended from pClassParent.
Example: _somDescendedFrom(_WPFolder, _WPObject) should return TRUE.
somResolveByName(pClassObject, "method") gives you a function pointer as
implemented by the specified class. You should assign this to a function
pointer variable which matches the function prototype, or otherwise
you'll get crashes.
Class replacements. Nowhere is really documented how class replacements
actually work, except that replacement classes must be direct descendants
of the class which is to be replaced. I assume that class replacements
are a feature of the SOM class manager, of which the WPS class manager is
a descendant (WPClassManager is half documented in the WPS Reference.) At
least there is a documented SOMClassMgr method, somSubstituteClass, which
appears to be doing exactly this job.
From what I've seen, class replacements seem to work this way: Any time a
class object is queried, the class manager does not return the class
object of the specified class, but the object of the replacement class
instead. As a result, all the method calls are not resolved for the
original class, but for the replacement class instead.
Examples: wpModifyPopupMenu is not called for WPFolder, but for XFolder
instead, even though the WPS had called it for a folder object. By
contrast, for wpQueryIcon, which is not overridden by XFolder, method
resolution leads to the method as implemented by the parent class, which
should be WPFolder, unless some other class replacements is present.
The class replacement mechanism is most obvious with the class object
macros described above: if you have a _WPFolder in your code, this
returns the class object of XFolder, i.e. _WPFolder == _XFolder. So if
you absolutely need the WPFolder class object, you call _XFolder and then
climb up the class object's inheritance tree using _somGetParent until
_somGetName returns "WPFolder".
To get the class object of any class without having access to its header
files, do the following:
somId somidThis = somIdFromString("WPObject");
SOMClass *pClassObject = _somFindClass(SOMClassMgrObject, somidThis, 0, 0);
Note again that _somFindClass will return replacement classes instead of
the originals. (That's how the class object macros work, BTW.)
__get_somRegisteredClasses(SOMClassMgrObject) returns a SOMClassSequence
of all currently registered class objects. This is used by the "WPS
classes" page in the "Workplace Shell" object. See classlst.c for
details.
ΓòÉΓòÉΓòÉ 4.7. XFolder Settings ΓòÉΓòÉΓòÉ
XFolder uses two kinds of settings: global and instance settings.
The global settings are set both in the "Workplace Shell" object and on the
"XDesktop" notebook page and are stored in the "XFolder" app in OS2.INI. All
the global notebook logic is in xfsys.c.
XFolder's code accesses these settings via a large structure called
GLOBALSETTINGS (suprise!) defined in common.h, to which a pointer be obtained
using cmnQueryGlobalSettings (common.c).
By contrast, the individual object settings are stored in instance data, which
is declared in the .IDL files. Most of these are stored and retrieved using the
normal WPS mechanism (wpSaveDeferred/wpRestoreData) and can have a certain
"transparent" value, which means that the global setting is to be used instead.
ΓòÉΓòÉΓòÉ 4.8. Subclassing Folder Windows ΓòÉΓòÉΓòÉ
XFolder subclasses all WPFolder frame windows to intercept a large number of
messages. This is needed for the majority of XFolder's features, which are not
directly SOM/WPS-related, but are rather straight PM programming.
The trick is just how to get "past" the WPS, which does a lot of hidden stuff
in its method code. By subclassing the folder frames, we get all the messages
which are being sent or posted to the folder and can thus modify the WPS's
behavior, since most of the default WPS methods are only called in response to
certain folder messages.
Subclassing is done in XFolder::wpOpen after having called the parent, which
returns the new frame window handle.
XFolder's subclassed frame window proc is called fnwpSubclassedFolderFrame
(also in xfldr.c). Take a look at it, it's one of the most interesting parts of
XFolder. It handles status bars (which are frame controls), tree view
auto-rolling, special menu features, the "folder content" menus and more.
This gives us the following hierarchy of window procedures:
1. our fnwpSubclassedFolderFrame, first, followed by
2. WPS folder frame window subclass, followed by
3. WC_FRAME's window procedure, followed by
4. WinDefWindowProc last.
If additional WPS enhancers are installed (e.g. Object Desktop), they will
appear at the top of the chain also. I guess it depends on the hierarchy of
replacement classes in the WPS class list which one sits on top.
In order to be able to relate the original frame window proc to a folder frame
(which can be different for each WPFolder window), XFolder maintains a global
linked list of PSUBCLASSEDLISTITEM structures (declared in common.h). This
might be a bit slow, but I have found no other way to store the original
window proc. Using window words does not work (believe me: it does crash the
WPS), because the window words seem to be used by the WPS already, and (of
course) this is not documented. If you have a better idea for this, let me
know.
As with all linked lists, XFolder uses the lst* functions in
/helpers/linklist.c for adding/removing/searching etc. list items. I have
developed these myself. If you have developed better funcs for doing this, let
me know. I don't claim mine are too effective, but I have found no better ones
which are thread-safe, and mine are because they allow for using mutex
semaphores.
ΓòÉΓòÉΓòÉ 4.9. Menu Manipulation ΓòÉΓòÉΓòÉ
This is perhaps the most complex part of XFolder. After all, this is what I've
started with, so some code parts may well be unchanged since December '97, when
I neither knew much about C nor about WPS programming.
With V0.81, all the logic for manipulating and evaluating context menus has
been moved to a new file, menus.c. All these functions have been given the mnu*
prefix to make this a bit clearer.
The XFolder classes override wpModifyPopupMenu and wpMenuItem[Help]Selected for
almost every replacement class. These overrides either handle the new context
menu items in that method code or, for XFolder and XFldDisk, call the functions
in menus.c, because these two classes share many common menu items, so we can
share most of the code also.
All newly inserted menu items use variable menu IDs. You can tell this from
their #define names, which have an _OFS_ in their name (check dlgids.h). To all
these values, XFolder adds the offset that is specified on the "XFolder
internals" notebook page.
For an introduction to how the config folder menu items work, see the "XFolder
Internals" section in the XFolder Online Reference. XFolder uses a fairly
obscure system of global variables to be able to relate menu items to their
intended functions. All the variable menu items are stored in a global linked
list when the context menu is opened for a folder. In each list item, XFolder
also stores what kind of object (template, program object, folder content item
etc.) the menu item represents. This list is then examined by
wpMenuItemSelected to perform the corresponding action (create a new object,
start program etc.). After that, the list is destroyed, so it only eats up
memory while the context menu is open. All this code is now (V0.81) in menus.c.
The folder content menus are initially only inserted as empty stubs. They are
only filled with items when they're opened: XFolder intercepts WM_INITMENU in
the subclassed folder frame proc (fnwpSubclassedFolderFrame, xfldr.c) and then
populates the menu. These menu items are stored in the global list too and
marked as folder content menu items so that wpMenuItemSelected will then simply
open the corresponding WPS object. The folder content code has now been moved
to menus.c also.
Painting the icons is then done using owner-draw menu items; the messages which
are necessary for this are also intercepted in fnwpSubclassedFolderFrame and
then call corresponding functions in menus.c.
Folder content menus are also subclassed to be able to intercept right-mouse
button clicks. The new window proc for this is called (suprise!)
fnwpFolderContentMenu and resides in xfldr.c.
The xfSelectingMenuItem method introduced in V0.80 has been removed again with
V0.81 due to the problems with SOM multiple inheritance.
ΓòÉΓòÉΓòÉ 4.10. Extended Sort Functions ΓòÉΓòÉΓòÉ
The default WPS sort functions are a mess, and I suppose IBM knows that, since
they have hardly documented them at all.
So here's what I found out.
The default sort criteria are all related to object details. That is, to
implement a sort criterion, you have to have a corresponding object detail, as
defined in the wpclsQueryDetailsInfo and wpQueryDetailsData methods.
There are many more object details than those shown in folder Details views. I
have counted 23 here (but your results may vary), and since there are only 13
columns in Details view, there should be about 10 invisible details. (Side
note: You can view all of them by turning to the "Include" page of any folder
and pressing the "Add..." button.)
Most of the details are defined in WPFileSystem's override of
wpclsQueryDetailsInfo, and if certain sort flags are specified there (even when
the details column is never visible), the WPS will make this detail available
as a sort criterion. That is, it inserts the column title in the "Sort"
submenu, shows it on the "Sort" page, and sets some corresponding comparison
function for the folder containers automatically.
This works beautifully for "real" subclasses of default WPS classes. For
example, you can create some subclass of WPDataFile, e.g. "WPAddress" for
storing addresses, define new object details for that class, set the "folder
sort class" of a folder to WPAddress, and you can then sort the folder
according to addresses automatically.
So, in theory, the whole details concept is great. You add new details to a
class, and the WPS can automatically sort, display the details, and even set
the "Include" options for folder accordingly.
But unfortunately, all the details/include/sort stuff is yet another example of
another great IBM concept which was only half implemented. I have found out the
hard way that XFolder cannot use this approch to extend the default sort
criteria. This is for the following reasons (believe me, I've tried all of the
following):
1. It is impossible to add new default details to an override of
WPFileSystem. Even if WPFileSystem is replaced with another class,
wpQueryFldrSortClass and wpQueryFldrDetailsClass do not return the
replacement class object, but the original WPFilesystem class object. I
have then tried to replace these two methods too, and details/sorting
would still not always work. There seem to be some ugly kludges in the
WPS internally.
2. Apparently, two sort criteria ("Name" and "Type") do not correspond to
any details columns. Normally, sort criteria are specified by passing the
corresponding details column to a sort function (see
wpIsSortAttribAvailable, for example). However, these two criteria have
indices of "-2" and "-1", so there seems to be some hard-coded special
case check in the WPS again. The "Type" criterion is even available when
WPObject is selected as the folder sort class, but WPObject does not
define that detail. So who knows.
3. The documentation for CLASSFIELDINFO is incomplete and partly incorrect.
I have tried to specify new sort functions in there, and the WPS would
just hang. Apparently the function prototypes are not correct, because my
own comparison function would never reach its first instruction before
the hang.
4. The wpQueryFldrSort and wpSetFldrSort methods are completely obscure.
They are prototyped using a PVOID parameter, and the documentation says
this should point to a SORTFASTINFO structure. But for one, this
structure is defined nowhere in the headers, and even more importantly,
the data passed to these methods does not correspond to the description
in the WPS reference. The first field in the structure is definitely no
sort function. So we have one more mystery there.
5. The most important limitation was however that there are no default
settings for sorting. The default sort criterion is always set to "Name",
and "Always sort" is always off. This is hard-coded into WPFolder and
cannot be changed. There is not even an instance method for querying or
setting the "Always sort" flag, let alone a class method for the default
values. The only documented thing is the ALWAYSSORT setup string.
Besides, the whole concept is so complicated that I only understood it now
after having debugged all the related methods for several days. I don't think
many users appreciate the flexibility of that concept or even know what "sort
classes" or "details classes" are about, even though there may be certain WPS
classes that use this concept.
The XFolder approach. It's basically a "brute force" method. XFolder lets the
WPS add the default sort features to context menus as usual, then adds its
own, and just intercepts all the menu ID's in wpMenuItemSelected.
I have then written a complete new set of container sort comparison functions
(in cnrsort.*) which do the job. So it's not the WPS at all any more which
does the sorting, but XFolder, and XFolder uses its own set of settings for
all this. See cmnSetCnrSort in xfldr.c for how this is done.
As you know, XFolder replaces the "Sort" page in folder settings notebooks
altogether too.
In addition, XFolder overrides the wpSetFldrSort method, which apparently gets
called every time the WPS tries to sort a folder. That is, normally, if one of
the "Sort" menu items would get called, but these are intercepted already by
XFolder. The override is still needed though because the WPS calls that method
frequently when "Always sort" is on also, e.g. when you rename a file.
Finally, there's a real neat hack to get access to the internal folder sort
settings, i.e. the settings that reside in the memory allocated by the
original WPFolder class. In wpRestoreData, which gets called when an object is
awakened, WPFolder always attempts to restore its folder sort settings from
the instance settings.
Since the caller always passes a block of memory to which wpRestoreData should
write if the data was found, we can intercept that pointer and store it in
XFolder's instance data. We can therefore manipulate the "Always sort" flag
also.
BTW, this can be used as a general approach to get access to WPS-internal
data, if a corresponding ulKey exists. Just override wpRestoreData (or the
other restore methods) and check for what keys they get called. Most of them
are declared in wpfolder.h in the Toolkit headers.
ΓòÉΓòÉΓòÉ 4.11. XFolder Threads ΓòÉΓòÉΓòÉ
XFolder is quite heavily multi-threaded and offloads most tasks which are
probable to take some time to the so-called "Worker" thread. XFolder uses mutex
semaphores all over the place to serialize access to global data structures.
Note that with V0.84, all the additional thread code has been moved from
xfdesk.c to a new xthreads.c file. This makes more sense and also reduces the
danger of unwanted side effects with large code files.
The Worker thread creates an object window to which other functions post
messages using xthrPostWorkerMsg to offload work. This object window's window
procedure is called xthr_fnwpWorkerObject, the main thread function is called
xthr_fntWorkerThread.
For example, the Worker thread maintains the global linked list of currently
awake WPS objects. XFldObject::wpObjectReady post WOM_ADDAWAKEOBJECT to the
Worker thread, which then adds the object to that list. (This list is needed by
XShutdown to store all the awake WPS objects; see the XFolder Online Reference
for details).
The Worker thread is created in XFldObject::wpclsInitData, which calls
xthrInitializeThreads. This is probably the first SOM method called when the
WPS is booting up, so I put this in here to allow the Worker thread to keep
track of really _all_ the objects.
The Worker thread runs at "Idle" priority, unless more than 300 messages have
piled up in its message queue. In this case, the priority is temporarily raised
to "Regular" and set back if the message count goes below 10 again. This can
happen when opening folders with a very large number of objects.
In addition, XFolder uses the "Quick" thread running at a high "Regular"
priority for things which won't take long but should not block the main WPS
(Workplace) thread. This thread creates an object window also. For example,
the new system sounds are played here.
The Quick thread is created together with the Worker thread and also displays
the most beautiful XFolder logo when it's started.
ΓòÉΓòÉΓòÉ 4.12. Playing Sounds ΓòÉΓòÉΓòÉ
The new system sounds are played in the "Quick" thread with high regular
priority. Check fntQuickThread and fnwpQuickObject for details about how this
is implemented using MMOS/2.
There are two above-average programming tricks related to this:
For one, nowhere is documented how to access and modify the system sounds
that appear in the "Sound" object. I have accidently discovered that this
is actually fairly easy: these are stored in MMPM.INI in the MMOS/2
directory. Each sound has an index in that file, which I have declared in
common.h (those MMSOUND_* #define's). These should be the same on every
system. The INI data then contains a "<soundfile>#<description>#<volume>"
string. Check cmnQuerySystemSound in common.c for details.
With V0.82, the actual playing of the sounds has been moved to a separate
SOUND.DLL because previously XFolder would refuse to install on systems
where MMPM/2 was not installed. This was due to the fact that if you link
a DLL against the MMPM/2 library functions, loading of the DLL fails if
these imports cannot be resolved. (Naturally, you don't get an error
message other than FALSE from the SOM kernel. This has taken me days to
find out.)
Now, if loading of SOUND.DLL fails (either because it's not there or
because the MMPM/2 imports of that DLL cannot be resolved), the new
system sounds are silently disabled. This happens in
xthrInitializeThreads.
Also, I've added much more sophisticated MMPM/2 messaging to check for
whether the waveform device is actually available. So playing sounds is a
process of communication between the Quick thread and SOUND.DLL now. See
the top of sound.c for more explanations.
ΓòÉΓòÉΓòÉ 4.13. XShutdown ΓòÉΓòÉΓòÉ
XShutdown (i.e. the "eXtended Shutdown" and "Restart WPS" features) has been
moved from xfdesk.c to a new file, xshutdwn.c, with V0.84.
XShutdown starts two additional threads to close all the windows. This is
described in detail in the "XFolder Internals" section of the XFolder Online
Reference. I have also tried to put plenty of comments into the sources.
ΓòÉΓòÉΓòÉ 4.14. XFolder Exception Handling ΓòÉΓòÉΓòÉ
XFolder registers additional exception handlers in certain parts where I
considered worth it.
With "worth it" I mean the following situations:
1. Certain code parts crashed on my system and these parts seemed
error-prone enough to me to outweigh the performance loss of registering
and deregistering exception handlers.
2. Exception handlers must be registered for all additional threads. If no
exception handling was registered there, crashes would take the whole WPS
down, because the default WPS exception handler only deals with the
default WPS threads.
3. Exception handlers must also be registered every time mutex semaphores
are used. If a code part crashes while a mutex semaphore has been
requested by a function, all other threads waiting for that semaphore to
be released will be blocked forever. And I mean forever, because even
DosKillProcess won't be able to terminate that thread. You'd have to
reboot to get out of this. So the exception handler must always check for
whether a mutex semaphore is currently owned by the thread and, if so,
release it.
XFolder does not use the VAC++ library funcs for all this, but installs its
own set of quite complex exception handlers (using DosSetExceptionHandler()).
With V0.84, the exception handlers have been moved from xfdesk.c to a new
file, except.c. That makes more sense.
Also, I have created a few handy macros which automatically register and
deregister the XFolder exception handlers. This avoids the frequent problem
that one forgets to deregister an exception handler, which leads to really
awkward problems which are almost impossible to debug. Those macros are called
TRY_xxx and CATCH to mimic at least some C++ syntax. See except.c for how to
install these macros.
The XFolder exception handlers are the following:
excHandlerPlus is the one that makes the loud sounds and writes the
XFLDTRAP.LOG file which is well-known to many XFolder users (grin). It
uses a longjmp() to get back to the function, which might then react to
that exception by trying to restore some safe state of the thread. See
the func header for details about how this works.
This handler is used by all the additional XFolder threads and also by
the subclassed folder frame and folder content menu window procs. This
slows down the system a bit because the handler must be registered and
deregistered for each message that comes in, but there's no other way to
do this. (I think.)
With V0.84, I have added lots of debugging code which I found in the
EXCEPTQ.ZIP package at Hobbes. The exception handlers are now capable of
finding symbols either from debug code (if present) or from a SYM file.
See the top of except.c for details.
excHandlerQuiet is similar to excHandlerPlus in that it uses a longjmp()
also, but neither is this reported to the user nor is the logfile written
to (that's why it's "quiet").
This is used in places where exceptions have ben known to occur and
there's no way to get around them. I created this handler for V0.80
because I found out that somIsObj() is not a fail-safe routine to find
out if a SOM pointer is valid, even though IBM claims it is.
(These were the strange errors in the Worker thread which appeared in
V0.71 when folders with subfolders were deleted, because the Worker
thread then tried to access these objects when the folder was populated
right before deletion.)
So I created the xwpsCheckObject func which can return FALSE, using this
handler, if access to the object fails.
ΓòÉΓòÉΓòÉ 4.15. Debugging XFolder ΓòÉΓòÉΓòÉ
Debugging WPS applications can be really tiresome, because you have to restart
the WPS for every tiny change you made to the source codes to take effect. And,
as with any PM program, you can't just printf() stuff to the screen. Even
worse, it's hard to use the PM debugger, because you have to start the whole
WPS (PMSHELL.EXE) with it, since XFLDR.DLL is no standalone application.
So I had to look for something else.
Those _Pmpf(("xxx")) thingies are for the magnificent PMPRINTF package by
Dennis Bareis. These only display anything if the proper DEBUG_xxx #define's
are set on top of common.h. For the release version of XFolder, all these flags
have been disabled, so no additional code is produced at all. You thus don't
have to remove the commands to speed up XFolder, because this wouldn't make any
difference.
Some files from the PMPRINTF package are included so that you can compile. The
PM interface which actually displays the messages is not however. Check Dennis
Bareis' homepage at http://www.ozemail.com.au/~dbareis/ where you'll find tons
of other useful utilities too.
However, to really use PMPRINTF, you'll have to put some DLLs on your LIBPATH.
See the PMPRINTF docs for details. I strongly recommend using this utility.
IMPORTANT NOTE: If you #define any of the flags at the top of common.h, you
must have the PMPRINTF DLLs somewhere on your LIBPATH, or otherwise you'll
spend days figuring out why XFolder is simply not working any more. (I had this
recently after a reinstall of OS/2, after which the DLLs where gone.) That is,
XFolder classes will not load at WPS startup, because the PMPRINTF imports
cannot be resolved. Neither will registering XFolder classes succeed. And don't
expect to get an error message other than FALSE. :-(
_Pmpf(("xxx")) uses regular printf syntax, except for those strange double
brackets, which are needed because macros don't accept variable parameter lists
otherwise.
Take a look at the top of common.h to find out more about the debugging flags.
ΓòÉΓòÉΓòÉ 4.16. Making XFolder ΓòÉΓòÉΓòÉ
If you wish to build the whole XFolder thing including the NLS DLLs and the INF
and HLP files, do the following:
1. Put the .EXE files in /TOOLS directory in a directory on your PATH. These
tools are required by the makefiles.
2. In MAKE.CMD in the main directory, you'll have to set a few variables.
This is explained in that file.
3. Call MAKE.CMD, which will recurse into the directories and possibly take
a long time. This will build the main DLL, the NLS DLL, and all the INF
and HLP files.
Note: Depending on whether the XFRELEASE environment variable is set, XFolder
will be compiled with debug code or not. This is determined in
/main/xfldr.mak. If this variable is not defined, you'll get the regular
XFLDR.DLL. If this variable is set to anything, a lot of debug code (including
line information) will be compiled into XFLDR.DLL, making that file more than
1 MB in size. This variable can be set in MAKE.CMD.
Makefiles. Each directory has its own makefile. All makefiles were written for
IBM NMAKE. I don't know if these will work with other make utilities.
/HELPERS no longer has its own makefile, because the sources in here will only
be used by the other XFolder parts, i.e. XFLDR.DLL, TREESIZE.EXE,
NETSCDDE.EXE. The .OBJ files for the helper sources are then created in the
directories of the respective XFolder part, because we might need different
compiler options for each part.
Rebuilding the whole thing. If you want to make sure that all C files are
recompiled, open and save /helpers/dosh.h to make it newer than the target
files. This is #include'd in all XFolder C files, and the makefiles' inference
rules will then enforce recompilation of all C files.
Alternatively, you can use CLEANUP.CMD, which will delete all the produced
files.
ΓòÉΓòÉΓòÉ 5. National Language Support (NLS) ΓòÉΓòÉΓòÉ
Overview
Requirements for translations
The main NLS DLL (XFLDRxxx.DLL)
The INF and HLP files
The HTML2IPF utility
Images and screenshots
Other files
Testing your NLS files
ΓòÉΓòÉΓòÉ 5.1. Overview ΓòÉΓòÉΓòÉ
Note: If you have already started translating XFolder, please do read the
changelog.txt file. There are important changes, or XFolder 0.81 might not run
with your NLS files properly.
Legal notes. XFolder is placed under the GPL, including the National Language
Support (NLS). If you translate the NLS part to your language, you create "a
work based on the Program" in the GPL sense. As a result, the GPL automatically
applies to your translation too.
This means that you have to publish your source code also.
Now, to move away from the Legalese, I suggest that you do not distribute
XFolder NLS packages yourself. Note that this is not a legal requirement (you
may do so if you ship the source code also), but for practical reasons, mainly
the following two:
For one, all the NLS packages should be available from my homepage for
convience.
Secondly, since I might update XFolder after you have finished your work on
your NLS version, XFolder might have trouble cooperating with your files.
Internal IDs might change and/or new features might be added. So if you have
finished creating your NLS package, please contact me, and I will put in on my
homepage and upload it to the usual places where XFolder is normally available.
This seems like the best solution to be, because I have a list of places which
carry XFolder, and I can update all the NLS packages myself when anything
changes with XFolder. This way, my homepage will always be the place to look
for up-to-date NLS packages.
Thus, when you're done translating, please zip up the complete directory tree
again and mail the ZIP file back to me.
How it works. XFolder NLS packages identify themselves to the XFolder core via
country codes, as described on the "COUNTRY" page in the OS/2 Command Reference
(CMDREF.INF). This package is prepared for creating the English NLS package, as
it comes with the default XFolder package. The language code for English is
"001".
So the first step you'll have to take is finding out your country code. For
example, Italian would be 039.
Unfortunately, XFolder's National Language Support (NLS) is spread across quite
a number of files, which have different file formats. These files are:
The NLS DLL to be put into the XFolder BIN subdirectory. This file
contains the language-dependent stuff which is needed by XFLDR.DLL.
notably dialogs, menus and miscellaneous strings.
The NLS DLL is called XFLDxxx.DLL, with "xxx" being your three-digit
language code. The files neccessary to translate this DLL are in the 001
directory.
See "The main NLS DLL" for details.
The XFolder message file introduced with V0.80 residing in the HELP
subdirectory. This file holds all kinds of messages which are mostly
displayed in XFolder's message boxes and are too large to be put into the
resources of the NLS DLL. This file is called XFLDxxx.MSG, with "xxx"
being your three-digit language code.
The source file for the MSG file is called XFLDRxxx.TXT (in the 001
directory also), with "xxx" being your three-digit language code.
See "The main NLS DLL" for details.
The XFolder Online Reference (INF) in the XFolder main directory.
This file is called XFLDxxx.INF, with "xxx" being your three-digit
language code. The files neccessary to translate this file are in the
001/INF.001 subdirectory.
See "The INF and HLP files" for details.
The XFolder HLP file in the HELP subdirectory. This file holds all the
help panels that are displayed when you press F1.
This file is called XFLDxxx.HLP, with "xxx" being your three-digit
language code. The files neccessary to translate this file are in the
001/HELP.001 subdirectory.
See "The INF and HLP files" for details.
The WPS class descriptions which are displayed on the "WPS Classes"
settings page in the "Workplace Shell" object. This was introduced with
XFolder 0.80 also.
This file is called XFCLSxxx.TXT, with "xxx" being your three-digit
language code. It also resides in the 001 directory.
See "Other files" for details.
A number of REXX .CMD and text files for XFolder's installation. The
files to be translated are in the MISC subdirectory.
See "Other files" for details.
The SmartGuide (Warp 4) script used for the XFolder introduction, which
is displayed right after XFolder has been installed and the WPS has been
restarted. This (XFLDRxxx.SGS) is also in the MISC directory.
See "Other files" for details.
The TOOLS directory contains a valuable tool for converting HTML files to the
IBM (IPF) format. This will be described on a separate page. This directory
also contains a few other needed tools. See the separate README in that
directory.
BTW: I'm really curious how "Snap to grid" sounds in your language. ;-)
ΓòÉΓòÉΓòÉ 5.2. Required Tools ΓòÉΓòÉΓòÉ
Even though all the source files in this package can be edited using any editor
(because they're all plain text files), you will need some extra utilities to
create the actual NLS files.
In any case, a C compiler is not required.
To be more precise:
The message file (XFLDxxx.MSG) can only be created if you have any
version of an OS/2 Developer's Toolkit (even 2.x should work), because
you will need MKMSGF.EXE to convert the .TXT file to .MSG format. See
"Other files" for more on this.
The same applies to the .INF and .HLP files: to build these from the .IPF
sources, you will need IPFC.EXE from the Toolkit; see "The INF and HLP
files" for details.
The makefiles in this package were written for IBM NMAKE, which comes
with all the IBM compilers. I'm not sure these will work with other MAKE
utilities. I'd be grateful for feedback.
The makefiles are only for conveniently updating the target NLS files. If
you don't have NMAKE, you have to assemble the files manually. See the
following pages for details.
ΓòÉΓòÉΓòÉ 5.3. The NLS DLL ΓòÉΓòÉΓòÉ
The files in the "001" directory contain everything neccessary to compile a
resource DLL (XFLDRxxx.DLL, with xxx being your country code). The resource DLL
contains strings, dialogs, and notebook pages.
Although the resources are contained in a DLL, the DLL contains no "real" code
(except for one dummy function, because every DLL needs to contain at least
some code).
Necessary preparations. Most files in this directory carry a three-digit
language code in their respective names; the files are prepared for English
(language code 001).
1. For your language, you need to change all the filenames with "001" in
their names to your country code (e.g. 039 for Italian).
2. You will also have to change the .DEF and .MAK files, which assume a
country code of 001 at this point. Required changes are noted in the
files themselves.
Note that all the dialog ID's access the dlgids.h file in the /MAIN directory.
Do not change anything in that file, or your WPS will behave really funny with
your NLS DLL. If you're lucky, that is. ;-)
Files that need to be changed:
xfldr001.def:The module definition file. Required changes are noted in
the file itself.
xlfdr001.mak: Makefile for IBM NMAKE. Required changes are noted in the
file itself.
xfldr001.rc, xfldr001.dlg: These are the main resource files which need
lots of changes.
I've documented everything you need to change in the .RC file.
The .DLG file is included when the RC files is recompiled. It contains
all the XFolder dialogs (i.e. notebook pages and other dialog windows).
Sorry, there are no comments in there because I'm using DLGEDIT.EXE to
create the dialogs, which rewrites the DLG file at every change, so all
comments in there get lost.
xfldr001.txt: This is the "source" file for the XFLDR001.MSG file. You
will need MKMSGF.EXE from the OS/2 Warp Toolkit to convert this plain
text file into a .MSG file. See the notes in that file.
Using a dialog editor. You can use DLGEDIT.EXE, the IBM dialog editor from the
Developer's Toolkit, to change the dialogs. (This will not affect the .RC
file.) For this, you will need to create the .RES file first (see
"Recompiling" below).
If you then open the .RES file with the dialog editor, you can choose
/main/dlgids.h as an include file so that all the numerical ID's have a more
meaningful name.
When you then save the file, the .RES and .DLG files will be recreated. The
.RC file remains untouched though.
The dialog editor has a helpful "Translate mode" in its "Options" menu which
disables a lot of menu items so you don't accidentally change dlg ID's or
other important stuff.
I don't know if you can use the URE editor also, I have not tried that.
Recompiling the DLL. If you have IBM VAC++, you can simply use MAKE.CMD to
have the DLL recreated. Everything should work fine, since all the neccessary
files are included.
Otherwise, things get a bit more complicated. Since the resource compiler
(RC.EXE) is already included with every OS/2 installation, you can try the
following:
1. Copy an existing XFolder resource DLL into your NLS DLL source directory;
rename it so that it contains your language code.
2. Open a command line in that directory.
3. Type rc xfldr001.rc xfldr001.dll (replace "001" with your language code),
which should create a new .RES file and link it against the existing DLL.
After recompiling, you can test the DLL as described in "Testing the DLL".
ΓòÉΓòÉΓòÉ 5.4. The INF and HLP Files ΓòÉΓòÉΓòÉ
The sources for the INF and HLP files are written using a slightly extended
HTML syntax. Creating INF and HLP files is therefore a two-step process:
1. The HTML sources are translated into an .IPF source file, using the
HTML2IPF utility.
2. Next, the .IPF source is fed into IBM's IPFC.EXE from the Developer's
Toolkit. This file is required to produce INF and HLP files, sorry.
Please use the MAKE.CMD file on the top level of the XFolder source files to
have the doc files created. This might take a while. You will first need to
set a few environment variables on top of MAKE.CMD, which is documented in
that file itself.
You then have two alternatives for the translations:
I recommend translating all the .HTML files and keep using MAKE.CMD to
have the HTML files converted into a single .IPF file (using the HTML2IPF
utility), which can then be fed into IPFC.EXE.
This has the advantage that you'll only have to change some panels in
future versions, of which I will keep track. Also, I always note changes
to the INF and HLP files in the HTML source files in HTML comments tags,
so you can easily search for what's changed.
The disadvantage is that, being a REXX program, HTML2IPF is slow.
You can also translate the one .IPF file in each of the INF and HELP
directories directly, if you're familiar with the IPF source language,
which is a proprietary IBM format (and which I don't like at all).
To do this, you'll have to create the two IPF source files first, using
MAKE.CMD. You can then translate this file and feed it into the IPFC.EXE
compiler to have the .INF and .HLP files created.
This has the disadvantage that if certain panels change in future
versions, you'll have no clue what parts changed in this single IPF file,
because the comments about changes are only visible in the HTML sources.
If you still want to use this method, please change the text only. Do not
change any resources, IPF tags, and especially not the resource ID's, or
XFolder will not find its help panels any more.
The "root" file in each of the two source directories is called XFLDRxxx.HTML,
respectively, with "xxx" being your country code (which you should change in
this one filename because HTML2IPF will use this name for the target IPF file
also).
To use HTML2IPF manually (instead of through MAKE.CMD), open a command line in
the INF or HLP directory (with XFolder ;-) ), and type:
<path>\html2ipf xfldr001.html
This will create a XFLDRxxx.IPF file (in the above example, XFLDR001.IPF). You
can then run ipfc XFLDRxxx.IPF to compile a HLP file; add an /INF switch to
produce an "INF" file. You must have the INF or HLP directory as your current
directory, or HTML2IPF will tumble.
If you don't have the Developer's Toolkit, there's no way you can actually
produce the INF and HLP files. You will have to use Netscape or WebExplorer to
view the help files, which of course are on many separate pages then. Begin
viewing XFLDRxxx.HTML in the INF and HELP directories, respectively.
In any case, mind these important notes:
The (slightly awkward, I admit) structure of the files is the following,
in both directories:
XFLDRxxx.HTML is the "root" file. Files beginning with "0" appear in the
contents tree of the produced INF and HLP files. All other files are
somwhere below in the INF/HLP table-of-contents hierarchy, depending on
the SUBLINKS tags in the HTML source files.
Do not change filenames! HTML2IPF sorts the IPF pages internally
alphabetically according to the filenames, that's why I've implemented
these strange naming conventions. I admit that since the structure has
developed over time, it may not seem very logical to you, but it works.
Changing things here will result in a lot of work, since all the links in
the HTML files will have to be renamed also.
Also, if you change the linkage of the HTML files, the resource IDs of
the help panels will be altered, and XFolder will then get confused
displaying the proper help panels.
Within the HTML files, do not change anything within angle brackets
("<xxx>"). Translate only the text outside of these. Even though some
tags might not be good HTML style and the HTML files might not look
pretty when viewed with Netscape, certain tag combinations (especially
the <BR><LI> combinations) are neccessary to make the pages look good for
IPF.
Don't forget to translate the page titles (in between the <TITLE> tags).
This is what appears in the title of a panel window and in the "Table of
contents" tree. I've forgotten this many times...
There are a number of files in the HLP directory which seem pretty
useless. These are neccessary however in order to guarantee a certain
sequence of the help panels in the resulting HLP file, on which XFolder
relies for calling a certain help panel. I don't quite understand myself
anymore how this order works, but it does, so I don't care. ;-)
I do not recommend translating everything for the INF book. I have done
the German translation myself, and I think that the "Revision history"
section makes no sense translating, because it is frequently updated and
NLS versions didn't exist for the older versions anyway. Also, the
"XFolder Internals" pages apply to programmers, which need to know
English anyway, because otherwise they won't find their way through the
required Toolkit docs either. So I think you can save yourself some work
there.
ΓòÉΓòÉΓòÉ 5.5. The HTML2IPF Utility ΓòÉΓòÉΓòÉ
The TOOLS directory contains the very valuable HTML2IPF tool by Andrew Pavel
Zabolotny. This REXX script is capable of creating a single .IPF file from a
list of linked HTML files, which can then be passed to IBM's IPFC.EXE for
creating .HLP and .INF files.
I have slightly modified this tool (see notes below).
Even if you don't know what I'm talking about, in this directory, you need to
open HTML2IPF.CMD and change three, maybe four things:
In line 27, translate the Resources on the Internet string.
In lines 28-31, translate the string beginning with This chapter
contains... translate every line, but do not mess with the '||'0d0a'x
codes and such.
In lines 34/35 translate the Click below to launch [code] with this URL:
string, but do not change the code in the middle.
In line 20, change the image converter; this is thoroughly explained in
the Images section.
Additional information (not obligatory)
I have included HTML2IPF.INF, which describes how the tool works. You need not
bother with this though, because everything is already set up properly.
I have changed HTML2IPF.CMD in a few places to allow for IPF window
positioning and certain extra character formatting. These changes are only
documented here, in case you're interested -- you will NOT find these changes
in the INF file (you don't have to know this, just if you're curious):
The <HTML> tag has new attributes: XPOS= and YPOS= work just like IPF's
"x" and "y" tags; WIDTH= and HEIGHT are the same as in IPF.
Added the strings described above to global variables for NLS.
The <A> tag accepts a new "AUTO=" attribute, which works just like
"HREF=", but automatically opens and closes the window (this is, for
example, used on the "Introduction" page of the XFolder Online
Reference).
The <CITE> and </CITE> formatting tags are now set to use a
non-proportional font, which is used extensively.
Some formatting changes (<UL>, <BR>, <B> etc.).
HTML2IPF now removes indenting spaces at the beginning of lines because
these would all appear in the INF/HLP files, while HTML ignores them.
(New with V0.81).
ΓòÉΓòÉΓòÉ 5.6. Images and Screenshots ΓòÉΓòÉΓòÉ
The images in both the INF and HELP directory are always available in both GIF
and uncompressed OS/2 1.3 BMP format. The reason for this is that HTML does not
support BMP, and IPF does not support GIF. :-(
HTML2IPF is very comfortable in this respect: it will automatically convert all
GIF images to BMP format every time it finds an <IMG> tag, but only if no BMP
file of the same filestem was found (see HTML2IPF.INF for details).
The image conversion program which HTML2IPF requires is specified in line 20 of
HTML2IPF.CMD. The original had Image Alchemy in here, I have changed it to
"GBMSIZE", which is part of the freeware "Generalized Bitmap Module" (GBM)
package available at Hobbes.
If you don't have GBMSIZE on your PATH, you can add the path to this
line.
If you wish to use a different converter, specify it here. Be careful
though: IPFC only supports uncompressed OS/2 1.3 bitmaps (see
HTML2IPF.INF). That is, neither compressed bitmaps nor Windows or OS/2
2.0 bitmaps work. This is annoying, because IPFC's own image compression
is totally outdated, but there's nothing we can do about this.
I'd be very grateful if you could create your own screenshots for the online
documentation, because I own German versions of OS/2 and for your NLS package,
screenshots of your language are preferrable, at least for those pictures
which have language-dependent stuff in them.
I have used the following settings for the screenshots (just for your
information, you don't have to use these):
Fonts used:
Titlebars: Humanist 521, 13 points (available on the
CorelDraw 4 CD in Type 1 format)
All the other fonts are set to 9.WarpSans.
CandyBarZ installed, colors:
Active: top 191/0/0, bottom 52/0/0
Inactive: top 160/160/130, bottom 40/40/40
Oh yes, XFolder installed. ;-)
Now, if you create your own screenshots, save them as GIFs with the exact
filenames of the originals (e.g. trunc.gif); you must then DELETE the
respective BMP file, because HTML2IPF will only call the image converter for
BMP if no BMP file of the same name exists.
Tricks to reduce file sizes:
Keep in mind that HLP/INF files have their own compression scheme which works
best when much redundant data is in the bitmap files. That is, large areas of
a plain color can be compressed best.
So taking screenshots of folders with background bitmaps is a no-no, because
this will really blow up the files.
And use as few colors as possible. You can use PMView to reduce the number of
colors to, say, 12 colors, which usually still looks alright. Make sure you
don't have "dithering" or "error diffusion" enabled, because this will add
lots of extra pixels which will make compression less efficient.
Also, if you need to scale images to a smaller size, make sure not to enable
any "interpolation", i.e. introducing extra pixels to make colors smoother.
This adds lots more colors to the file, which cannot be compressed well.
ΓòÉΓòÉΓòÉ 5.7. Directory "MISC" ΓòÉΓòÉΓòÉ
The MISC directory contains files used by XFolder's installation script
(INSTALL.CMD) plus the SmartGuide Script used for the XFolder introduction.
INSTxxx.MSG (with "xxx" being your country code, which you need to
change) is -- I'm sorry -- in a proprietary format. It's not difficult to
understand though: The file is used by XHELP.CMD (in the XFolder
package), which is capable of extracting single text messages in between
the <TOPIC>; and </TOPIC> tags in this file. The text between these tags
is then displayed on the screen.
Please note that this file will disappear in a future release of XFolder,
as soon as the WarpIn installer is functioning, which I am currently
working on. See my WWW homepage for details.
If you still wish to translate this file, what you need to do here is
simply translate all the text which follows a <TOPIC> tag. The text is
displayed "as is", and no formatting is performed; as a result, you must
take care that no more than 80 characters are contained in a line.
You also should take care of the line breaks: it makes a difference in
output whether a </TOPIC> end tag is found at the end of a line or at the
beginning of a new line, because in the latter case, the line break is
still printed to the screen.
Just one more note: Do not change the keys mentioned in this file ("X",
"Y", "N"), even if your language does not use "Y" for saying "Yes".
Unfortunately, INSTALL.CMD relies on these keys. :-(
CROBJxxx.CMD is a straightforward REXX script which creates the default
XFolder Configuration Folder. Even if you don't know REXX, don't worry:
you only have to change the strings on top of the file, which contain all
the language-dependent things. Be careful with the quotes. Do not change
anything else, because XFolder relies on it.
SOUNDxxx.CMD is the REXX script which creates the neccessary INI entries
for having the new XFolder system sounds in your "Sound" object. Only
change the strings at the top of the file to your language.
XFLDRxxx.SGS is a Warp 4 SmartGuide script to display the "Welcome"
window after XFolder has been installed and the WPS has been restarted.
I have no idea what the precise syntax for these files is (once again has
IBM developed good software, but then lets it rot), but it seems to be
some HTML-like syntax, except that the tags MUST be in lower case, or
they won't work.
ΓòÉΓòÉΓòÉ 5.8. Testing Your NLS Files ΓòÉΓòÉΓòÉ
XFolder's NLS depends entirely on a single entry in OS2.INI
("XFolder"::"LanguageCode"). This entry defaults to a "001" string and can be
changed either at installation time (if the install script does it) or by using
the "Language" setting in the "Workplace Shell" object, "XFolder" page 2.
All NLS resources are loaded depending on this one setting. That is, if you
change the language, XFolder expects not only your NLS DLL to be present in
/BIN, but also the MSG, HLP, and WPS class description files in /HELP. So if
you have not translated these yet, you might want to create a copy of the
English ones with your language code in the filename.
To test a new version of your NLS files:
Make sure you do not currently have your new NLS DLL selected on the
"XFolder Internals" settings page, because if you do, the DLL is locked
by XFolder and cannot be replaced.
Select "US English" instead, which will unlock the previously used DLL,
which can then be deleted from the XFolder directory.
Then put your new DLL into the BIN subdirectory and open the settings
again; select your DLL and see if things work.
Additional caveat for INF/HLP files: Before compiling the .IPF to the
.HLP/.INF files, you should make sure that the target file is not
currently in use.
With INF files, that's easy: simply close it if it's open.
With HLP files, you have to keep in mind that the WPS keeps these files
locked even after you've closed a help panel window. However, the WPS
only ever keeps a single HLP file locked at a time, so in order to unlock
the XFolder HLP file, simply open a default WPS help panel, e.g. by
selecting "Extended Help" for the Desktop window.
You can then copy the new XFolder .HLP file to the XFolder HELP
directory. (MAKE.CMD will do this automatically.)
ΓòÉΓòÉΓòÉ 6. Resources on the Internet ΓòÉΓòÉΓòÉ
This chapter contains all external links referenced in this book. Each link
contained herein is an Unified Resource Locator (URL) to a certain location on
the Internet. Simply double-click on one of them to launch Netscape with the
respective URL.
ΓòÉΓòÉΓòÉ 6.1. http://www.edm2.com ΓòÉΓòÉΓòÉ
Click below to launch Netscape with this URL:
http://www.edm2.com
ΓòÉΓòÉΓòÉ 6.2. http://www.ozemail.com.au/~dbareis/ ΓòÉΓòÉΓòÉ
Click below to launch Netscape with this URL:
http://www.ozemail.com.au/~dbareis/
ΓòÉΓòÉΓòÉ 6.3. http://www2.rz.hu-berlin.de/~h0444vnd/os2.htm ΓòÉΓòÉΓòÉ
Click below to launch Netscape with this URL:
http://www2.rz.hu-berlin.de/~h0444vnd/os2.htm
ΓòÉΓòÉΓòÉ 6.4. mailto:ulrich.moeller@rz.hu-berlin.de ΓòÉΓòÉΓòÉ
Click below to launch Netscape with this URL:
mailto:ulrich.moeller@rz.hu-berlin.de
ΓòÉΓòÉΓòÉ 6.5. notices_3comments.html ΓòÉΓòÉΓòÉ
Click below to launch Netscape with this URL:
notices_3comments.html