directory structure

Please note that the following discussion is not a tutorial on the creation of a LiteStep theme - it merely explains what properties a LiteStep theme must have in order to be OTS compliant.

The first aspect of themes the OTS addresses is their directory structure. All OTS compliant themes should have a structure similar to that of 'theme-X' as shown below. Note that all themes are stored in subfolders of the 'themes' directory. The location of the 'themes' directory will vary depending on the end-user's platform (9x/NT) but this is of no concern to a themer. Indeed, a themer need not worry about the precise location of a folder in the LiteStep hierarchy outside of their theme since evars are available for any folder that a themer might need to reference.

theme-X directory

As far as the directory structure of themes goes, all a themer needs to do is respect certain conventions. The directories shown above such as 'config', 'images', 'misc', etc. are not compulsory, they are only to be used as required. For example, if a theme does not include wallpaper, it has no need for a 'wallpaper' directory and this can be omitted. But if a theme does include wallpaper, it should be stored in a 'wallpaper' directory, not in the root folder of the theme (i.e. $ThemeDir$) or in a 'bg' folder, etc.

Themers are free to create subfolders wherever they are required, this is often done in the 'images' and 'config' directories of more complex themes.

The following table provides a quick overview of the directories relevant to the current discussion. Please note that all locations have been defined in reference to the 'themes' directory.

Directory Evar Location Description
themes $ThemesDir$ X:\LiteStep\themes\ (Win9x)

...\Application Data\LiteStep\themes\ (WinNT)

user-defined via the $ThemesDir$ evar in step.rc
all LiteStep themes are contained in subfolders of this directory - at the root level, it contains themeselect.rc, the file that specifies which LiteStep theme is in use
theme-X $ThemeDir$ ...\theme-X\

user-defined via the $ThemeDir$ evar in themeselect.rc
root directory for LiteStep theme currently in use - at the root level it contains theme.rc and hopefully, some theme documentation
config $ConfigDir$ ...\theme-X\config\

themer-defined (if needed) via the $ConfigDir$ evar in theme.rc
contains theme configuration files such as popuptheme.rc and themevars.rc - in fact all theme configuration files other than theme.rc are stored here
images $LSImageFolder$ ...\theme-X\images\

themer-defined (if needed) via the $LSImageFolder$ evar in theme.rc
all theme graphics are stored in this directory
misc $MiscDir$ ...\theme-X\misc\

themer-defined (if needed) via the $MiscDir$ evar in theme.rc
this is the place to store the odds and ends related to a theme that don't fit anywhere else: fonts, skins, etc.
sounds $SoundsDir$ ...\theme-X\sounds\

themer-defined (if needed) via the $SoundsDir$ evar in theme.rc
contains any sound files required by a theme
wallpaper $WallpaperDir$ ...\theme-X\wallpaper

themer-defined (if needed) via the $WallpaperDir$ evar in theme.rc
contains any wallpaper images included with a theme

The following section deals with the key theme related files stored in the directories that were just examined.

key files

$ThemeDir$theme.rc

This is the main theme configuration file, and as such it has several significant purposes:

  • specify what version of the OTS the theme adheres to
  • specify the theme's and themer's names
  • define theme directory evars as required
  • load litestep modules
  • specify settings for litestep modules

The first section takes care of the first three points. It specifies the name of the theme, that of the themer, and defines evars for the 'config' and 'images' directories. Defining the names is mandatory, but (as mentioned earlier) the folder evars need only be defined if required.

The $OTSMajorVersion$ and $OTSMinorVersion$ evars are compared against the $OTSCfgMajorVersion$ and $OTSCfgMinorVersion$ evars in theme.rc respectively, during theme installation. Apart from this vital function, these evars are useful for documentation and support, allowing users to immediately discern whether a theme is OTS compliant, and if so, which version it adheres to.

The last thing being done in the first section is the inclusion of themevars.rc and popuptheme.rc. These files will be discussed shortly, and only need to be included if the theme requires them.

;------------------------------------------------------------------------------
;    LiteStep environment config
;------------------------------------------------------------------------------

OTSMajorVersion 2
OTSMinorVersion 0

ThemeName       "theme-X"
ThemeAuthor     "Themer X"

ConfigDir       "$ThemeDir$config\"
LSImageFolder   "$ThemeDir$images\"

include         "$ConfigDir$themevars.rc"
include         "$ConfigDir$popuptheme.rc"



;------------------------------------------------------------------------------
;    load modules
;------------------------------------------------------------------------------

*NetLoadModule  popup2-2.0
*NetLoadModule  desktop2-2.0
*NetLoadModule  RabidVWM-1.01
*NetLoadModule  rainmeter-0.9 load rainmeter.dll


;------------------------------------------------------------------------------
;    module config
;------------------------------------------------------------------------------

include         "$ConfigDir$base.rc"
include         "$ConfigDir$popup.rc"
include         "$ConfigDir$vwm.rc"
include         "$ConfigDir$stats.rc"

The second section loads all modules used by the theme via NetLoadModule. This is a significant departure from the past, when modules were bundled with themes and loaded directly via LoadModule statements. Modules are no longer included with themes - they are downloaded automatically via NetLoadModule, and loaded via *NetLoadModule statements. This will be discussed in complete detail in loading modules.

Note that themes should never load a hotkey module. Any hotkey module loading will be done by the user in personal.rc. (Hotkey assignments can of course be specified as usual, but they should be in themevars.rc.)

The last section is where all the settings for the various modules are specified. They can be specified directly in theme.rc or (as is more commonly done) split into different files and then added to theme.rc via include statements.


$ConfigDir$themevars.rc

This file contains all theme settings that are meant to be edited by the user. This includes things like theme-specific evars, hotkeys, etc. A sample themevars.rc is shown below:

HotspotsOn              true

*Hotkey CTRL+SHIFT X    !FocusCommand

SCBAR1 "C:\Program Files\MegaShaft\monopoly.exe"
SCBAR2 "C:\Program Files\MegaShaft\dojinpocket.exe"
SCBAR3 "$FileManager$"
SCBAR4 "$TxtEditor$"

Putting theme settings like these into themevars.rc allows end users to easily customize them according to their preferences and system.

Application evars in particular are quite important - theme configuration files should never contain any explicitly specified paths. Instead, application evars should be defined in themevars.rc and used in the theme as required. For example, the sample themevars.rc shown above allows for the configuration of a shortcut bar in the following manner:

*Shortcut "" 215c -19 sc_1.bmp .none .none #1 "$SCBAR1$"
*Shortcut "" 234c -19 sc_2.bmp .none .none #1 "$SCBAR2$"
*Shortcut "" 250c -19 sc_3.bmp .none .none #1 "$SCBAR3$"
*Shortcut "" 266c -19 sc_4.bmp .none .none #1 "$SCBAR4$"

So end-users user can simply edit themevars.rc to customize key aspects of the theme, rather than digging through theme configuration files looking for the settings they need to change.

The use of themevars.rc is not mandatory, but it should be employed whenever a theme needs to make settings readily available to the end-user for customization, or an absolute path needs to be specified, etc.

Please note that setting up themevars.rc deliberately so that a theme fails to load or produces errors unless it has been edited, is forbidden. For example, a themer might intentionally not define an evar to see if a user is paying attention:

;--> set this evar to your favourite search engine's webpage
WebSearchLink

Users should be editing themevars.rc before loading a theme, but there's no need to make them suffer if they don't. Themes should load just fine, even if the user has not edited themevars.rc. The following approach is far more civil:

;--> set this evar to your favourite search engine's webpage
WebSearchLink   "http://why.didnt.you.edit.themevars.rc.com/"


$ConfigDir$popuptheme.rc

This file defines a theme-specific popup menu that is accessed by SHIFT-left-clicking on the desktop. The contents of this popup menu are entirely themer-defined - the only requirements are that popuptheme.rc must begin with the following line:

*Popup "theme-X" !New !PopupTheme

and end with this one:

*Popup ~New

The "theme-X" label is obviously to be replaced by whatever title is desired for the popup menu. Incidentally, although the contents of the right-click popup menu are entirely user-defined (via popup.rc), the title of this menu may be specified by a theme as usual with the HotlistName setting.

The theme-specific popup menu is an optional component, themes are not required to provide one.

loading modules

As mentioned during the discussion of theme.rc earlier, modules are no longer distributed along with themes, they are downloaded and then loaded via NetLoadModule instead.

Themers do not need to specify any settings for NetLoadModule, it is already configured in step.rc to do the following:

  • download modules from shellfront.org or ls-universe.info
  • install downloaded modules in $ModulesDir$
  • install module documentation in $ModulesDir$docs\
  • archive downloaded module packages in $ModulesDir$archive\

The following concepts should be understood before proceeding:

  • archive name - the filename of a module's archive, minus the extension
    example: the archive name of modulex v1.2, archived in modulex-1.2.zip, is modulex-1.2
  • module name - the filename of the .dll inside the module archive that is to be loaded by LiteStep
    example: modulex.dll (this assumes of course that modulex-1.2.zip contains a modulex.dll which is the .dll to be loaded by LiteStep)
  • for archives that contain only one .dll - the LiteStep module is installed as "$ModulesDir$archive name.dll"
    example: after being downloaded by NetLoadModule, modulex v1.2 is installed as "$ModulesDir$modulex-1.2.dll"
  • for archives that contain more than one .dll - the LiteStep module is installed as "$ModulesDir$archive name\module name"
    example: after being downloaded by NetLoadModule, modulex v1.2 is installed as "$ModulesDir$modulex-1.2\modulex.dll"

The only thing a theme normally has to specify is the archive name of the module to be loaded, via *NetLoadModule statements as shown below - there are exceptions to this though, which slightly complicates matters. Please pay attention as the following information can be critical for the correct installation and operation of themes.

;the norm: module archive contains only one .dll
*NetLoadModule  dynamp-0.43
*NetLoadModule  jamptoo-1.3
*NetLoadModule  rabidvwm-1.01

;exceptional case: module archive contains more than one .dll
*NetLoadModule  rainmeter-0.9 load rainmeter.dll

If a module archive contains only one .dll file (i.e. the .dll that is to be loaded by LiteStep) then it can be loaded simply by specifying the archive name in a *NetLoadModule statement. For example, RabidVWM v1.01 is archived as rabidvwm-1.01.zip, and upon examination of the archive one finds that it contains only one .dll file: rabidvwm.dll. Therefore it can be loaded via the following *NetLoadModule statement:

*NetLoadModule  rabidvwm-1.01

A slight complication arises when a module archive contains more than one .dll file. In this situation, NetLoadModule has to be told which of the .dll files in the archive is the one to be loaded by LiteStep.

In order to do this, the load option must be used in the module's *NetLoadModule statement. The load option takes an argument of the form "modulex.dll", where modulex.dll refers to the module name as defined earlier.

Rainmeter is an example of a module whose archive contains more than one .dll file. Rainmeter v0.9 is archived as rainmeter-0.9.zip, examination of the archive shows that it contains several .dll files. The .dll file to be used with LiteStep is rainmeter.dll, therefore it should be loaded in the following manner:

*NetLoadModule  rainmeter-0.9 load rainmeter.dll

In summary, the following procedure is to be used by themers when formulating *NetLoadModule statements:

  1. download the module archive from shellfront.org or ls-universe.info and store it in a temporary location*
  2. examine the filename of the downloaded archive - it will be of the form modulex-1.2.zip
  3. add the following *NetLoadModule statement to theme.rc:
    *NetLoadModule modulex-1.2
  4. open modulex-1.2.zip (the downloaded module archive) and examine its contents
  5. if modulex-1.2.zip contains only one .dll file, the *NetLoadModule statement is complete.
    if there is more than one .dll file in the archive, then use the appropriate load option, resulting in:
    *NetLoadModule modulex-1.2 load modulex.dll

*If the module is not available from shellfront.org or ls-universe.info, a URL for the module can be specified in its *NetLoadModule statement - see NetLoadModule's documentation for details.

Please ensure that the naming convention (modulenameinlowercase-moduleversion) is adhered to in these situations. For example, the following *NetLoadModule statement can be used to load IconDesk v0.55 from ls-universe.info:

*NetLoadModule icondesk-0.55    "http://www.modules.ls-universe.info/modules/icondesk-0.55.zip"

loading modules for use with LSBox (or a wharf)

(Please note that the following procedure was written with LSBox in mind, but is equally valid for a wharf.)

In order to use a module with LSBox, it should not be installed and loaded with a *NetLoadModule statement, but simply installed with a *NetInstallModule statement instead. The syntax for *NetInstallModule is the same as for *NetLoadModule. Please consult NetLoadModule's documentation for details.

Module installation is thus handled by NetLoadModule, and module loading will be left to LSBox as usual. Loading a module from a .box file will require an understanding of the difference between modules whose archives contain multiple .dll files, and those whose archives contain only one, as discussed earlier.

By way of example, if rainmeter and vtray were to be loaded via .box files, one would first have to ensure that the modules are installed. This can be achieved by adding the following statements to theme.rc:

*NetInstallModule  vtray-1.06
*NetInstallModule  rainmeter-0.9 load rainmeter.dll

To load the modules, simply add correctly formulated statements (paying particular attention to module paths) to the .box files, e.g.:

*WharfModule 10 0  70 18 $ModulesDir$vtray-1.06.dll
*WharfModule 80 0 120 18 $ModulesDir$rainmeter-0.9\rainmeter.dll

additional notes

desktop settings

As explained in the specification, the OTS provides for two standard popup menus accessed by clicking the desktop: a user-defined right-click popup menu, and a themer-defined SHIFT-left-click popup menu. The desktop settings that control the launching of these menus are in personal.rc:

*Desktop RButton !Popup                         ;right-click popup menu
*Desktop LButton+SHIFT !PopupTheme              ;SHIFT-left-click popup menu

*jDeskMButton2 [.none;!none;!Popup;!none]       ;right-click popup menu
*jDeskMButton1 [SHIFT;!none;!PopupTheme;!none]  ;SHIFT-left-click popup menu

Since the right-click and SHIFT-left-click settings for the desktop have already been defined, they should never be specified by a theme.

lsxcommand settings

A search engine file for lsxcommand (engines.list) and a history file (history.ini) are available in $PersonalDir$lsxcommand\, so there is no need to include these files with themes.

The following lsxcommand options should not be specified by themes since they are already set in personal.rc:

CommandSearchEngineList "$PersonalDir$lsxcommand\engines.list"
CommandHistoryFile      "$PersonalDir$lsxcommand\history.ini"
CommandHistoryEntries   20

rainlendar settings

A general rainlendar configuration file (rainlendar.ini) and a rainlendar events file (events.ini) are present in the 'rainlendar' subdirectory of $PersonalDir$ and as such should never be included with themes. The following settings are present in personal.rc and should not be specified by themes:

RainlendarPath          "$PersonalDir$rainlendar\"
RainlendarEventsPath    "$PersonalDir$rainlendar\"
RainlendarLanguagesPath "$PersonalDir$rainlendar\languages\"

module settings in general

Themes should not use any settings that have already been specified in personal.rc. One simple way to prevent this is for themers to check their local personal.rc file as they're developing their themes.

If a theme does repeat a setting that occurs in a user's personal configuration files, it may not actually cause any problems since the user's settings should take precedence.

In addition to checking personal.rc, a simple rule to follow is to only use those settings in a theme that are absolutely required by the theme. This will help reduce some of the clutter in theme configuration files, minimize the risk of setting conflicts, and is simply common sense. Why specify a setting that has no impact on a theme's functionality but may affect general usability? Such settings should be controlled by users in their personal configuration files.

Let us take for example, the following lsxcommand settings:

;clear lsxcommand's history on startup
CommandClearHistoryOnStartup

;suppress error message for invalid commands
CommandNoWarnOnError

There is no conceivable reason why a theme would depend on these settings, and hence no justification for including them in theme configuration files. These settings are clearly a matter of personal preference, and should be specified in personal configuration files.

Once again: only use those settings in a theme that are absolutely required by the theme.

quoting evars

Any evar that references a folder should be quoted, because the complete path to the folder might contain spaces. Consider the following file inclusion statement:

include $ConfigDir$scheme.rc

$ConfigDir$ will have been defined in theme.rc to point to the 'config' subdirectory of the theme, as required by the OTS. If the full path to the 'config' folder is devoid of spaces, e.g. 'C:\LiteStep\themes\theme-X\config', then the above statement will be fine. However if the path has one or more spaces, e.g. 'C:\Program Files\LiteStep\themes\theme-X\config' the include statement will be interpreted incorrectly, and will fail.

The following statement however, will work fine in all situations:

include "$ConfigDir$scheme.rc"

This is merely an example, the problem is not limited to include statements, all evars that reference folders are affected. Therefore, all evars used to reference folders in any way must be quoted. This cannot be stressed enough, and is of paramount importance to the correct operation of themes.

theme documentation

Themes should include documentation in $ThemeDir$, preferably named "readme.txt" or "readme.htm". As an absolute minimum, the following should be provided as "$ThemeDir$readme.txt.":

ATTENTION: If this is the first time you are using an OTS compliant theme,
           please go to: http://o-t-s.sf.net/theme_installation.html

If care is taken to create a theme properly, the generic installation instructions will be sufficient to get it installed and running.

Themers should at least make a note of the operating system the theme was developed on, any issues the user should be aware of, and anything in general that users should know when installing or using the theme.

theme packaging

When archiving a theme, only the root directory of the theme should be included as part of the path information (including subfolders of course). Another way of putting this is that themes should be packaged in such a way that they can be extracted to the 'themes' directory (i.e. $ThemesDir$).

An examination of the following screenshot should clear up any remaining confusion surrounding this issue:

theme-X archive

OTS compliant themes should be compressed with any standard zip utility. After a theme has been archived, it should be renamed to have an '.lsz' extension, e.g. 'theme-X.zip' would be renamed to 'theme-X.lsz'.

Having a unique extension for LiteStep themes allows for them to be immediately identified visually, to be searched for and sorted with greater efficiency, and to be installed automatically by utilities such as the LiteStep Theme Installer, included with the LiteStep Installer.

Users of the LiteStep Installer are provided with the means to handle '.lsz' files, but users that choose not to use theme installation utilities are not stranded since they can simply associate the '.lsz' extension with their preferred '.zip' utility and handle theme installation manually.

checklist

An OTS compliant theme should have all of the following qualities:

  • main theme configuration file named theme.rc
  • any other theme configuration files stored in 'config' subdirectory of theme
  • theme.rc defines $OTSMajorVersion$, $OTSMinorVersion$, $ThemeName$, $ThemeAuthor$
  • appropriate subdirectories used as required, e.g. 'config', 'wallpaper', etc.
  • theme.rc defines any needed subdirectory evars e.g. $ConfigDir$
  • themevars.rc used to provide end-user adjustable settings or specify absolute paths
  • popuptheme.rc used as needed
  • all modules loaded via *NetLoadModule, not LoadModule (and no modules should be included with the theme)
  • *NetLoadModule statements must use the load option for modules whose archives contain more than one .dll file, and be properly formed in general
  • no hotkey module should be loaded, hotkey module loading handled in personal.rc
  • module settings in personal.rc for desktop, lsxcommand, rainlendar, etc. not repeated in theme
  • only settings vital to the theme's appearance and function should be specified
  • evars used to reference folders in any way must be quoted
  • documentation provided in $ThemeDir$
  • packaged with correct path information
  • theme archive should be compressed with a '.zip' utility and renamed to have an '.lsz' extension
  • a user's personal config. files (personal.rc, popup.rc, etc.) may not be modified by a theme

updating old themes

The OTS has changed significantly since its last release, and older OTS compliant themes will have to be updated accordingly.

This is unfortunate, but unavoidable. Hopefully the process will not be too traumatic, and in the future revisions to the OTS will be made incrementally in a timely manner, rather than in radical bursts after a lengthy calm.

The following is an outline of the process one could follow when updating an older OTS compliant theme:

  1. rename $ThemeDir$step.rc to theme.rc
  2. remove definitions of $ModulesDir$, $PersonalDir$, $ShortcutsDir$, and $ThemeDir$ from theme.rc
  3. add definitions of $OTSMajorVersion$ and $OTSMinorVersion$ to theme.rc
  4. remove inclusion of personal.rc from theme.rc
  5. delete any hotkey LoadModule statement
  6. delete any settings that have already been specified in personal.rc (e.g. for desktop modules, lsxcommand, and rainlendar)
  7. delete 'modules' subdirectory if present
  8. replace all LoadModule statements with their *NetLoadModule equivalent
  9. revise any configuration files affected by the above changes

The last point regarding the revision of affected configuration files is worth expanding on. For instance, any scripts that were manipulating the contents of $ThemeDir$step.rc will have to be revised to work with $ThemeDir$theme.rc instead. Any settings making use of $ShortcutsDir$ will have to be changed since this evar is no longer available. !ReloadModule and !Unloadmodule commands will have to be revised in accordance with NetLoadModule's abilities, e.g. this:

!ReloadModule     $ModulesDir$ckhotspots.dll

would become:

!NetReloadModule  ckhotspots-2.3

(One could still use !ReloadModule and !UnloadModule, but using the NetLoadModule equivalents is much simpler.)

Please note that these are merely illustrative examples, there are many other cases in which such revisions would be required.

The changes are for the most part, quite straightforward and can be made without too much difficulty. A text editor with a powerful search and replace feature would prove quite useful though.