## readme-developers.html

### Table of Contents

1. Code changes
2. MakePatchDirs
3. Minor code changes and bug fixes
4. Coding conventions
5. Doxygen comments
6. RCS Ids
7. File release numbers
8. Packaging file releases
9. Tagging CVS when releasing files
10. Localization : resources files
11. Localization : merging and scheduling
12. Logging
13. Shell Extension

### Code changes

In 2003 WinMerge has seen a happy spurt in development activity. Several new developers have joined in actively with developer cvs access, and also some users have contributed elaborate patches, and participated in ongoing discussions.

This is exciting, and also leads to a fair amount of rapid change, so we adopted some guidelines to help safeguard our WinMerge development somewhat.

The original guidelines suggested were posted to the developer's mailing list (which is not archived). What is documented here is the actual procedures which we have been following, which are of course similar, as we developed our actual procedures based on the original suggested guidelines.

If you do not like some part of these guidelines, please feel free to post a message to the developer's mailing list or the developer's forum discussing the matter.

1. Post development intentions:

   - If you are fixing a bug, put a note in the SourceForge bug report that you're fixing it. If there is no SourceForge bug report, create one.
   - If you are implementing a new feature, put a note in the SourceForge RFE (request for enhancement) that you're implementing it. If there is no SourceForge RFE, create one.
   - If you are rewriting or refactoring code, and the change is not small, then post your intent. The developer's mailing list or the developer's forum at SourceForge would be good places to post your plan.

2. Before you start developing, make sure to capture a snapshot of your starting sources (presumably a pristine copy of cvs sources, or of a source zip from a distribution).

3. Review the sections on Coding conventions and Doxygen comments

4. Develop your new version.

5. Post your changes as a patch, to the SourceForge patch list. Try to give an informative patch title of course. Post to any relevant SourceForge bugs or RFEs, giving the patch number and title.

   The active developers have often been posting entire original and modified files rather than traditional diffs, because obviously all developers have access to WinMerge to compare original and modified files, and this may be viewed as an infinite line context diff :)

6. Wait for reactions from other developers (and sometimes active users). If you feel impatient, you may solicit review of your patch via the developer's mailing list.

7. After a reasonable amount of time has passed, and no negative reviews have been posted (or after you have responded to and dealt reasonably with any that have been posted), apply the patch to CVS. (Or ask a project member to do so, if you have not yourself developer access to the project.)

   What is a reasonable amount of time? That is somewhat subjective, and we need to rely on your expertise as the patch developer, but let us suggest waiting a few days for minor patches, and at least a week for major patches.

8. Add a note in `readme.txt` telling what files you committed, and what bug/RFE/patch you solved. This is very important so everybody else has a change to figure out who did what and when.

### MakePatchDirs

Perry wrote a small program called MakePatchDirs, which helps in his patch process -- read the link for more information.

### Minor code changes and bug fixes

It is reasonable to post small snippets of code showing small changes directly in the text in bug postings, or patch postings. For example, see PATCH [ 824987 ] "Change binary-file detection (look only for zeros)", which gives the change directly in the text.

Note, however, that sourceforge trackers currently ignore tabs, so if can convert tabs to spaces in your posting, it helps greatly.

Bugfixes may be treated less formally, especially for simple ones, or for fixes to code you know well -- eg, you caused the bug yourself with a recent patch :)

Consider still posting something to the tracker lists, even if it is simply a summary in English. If the fix is something like "misspelled variable name foo as fooz in many places", it is quite understandable that you prefer to just fix the instances rather than doing a full patch for it.

### Coding conventions

Please conform to the prevalent coding conventions. There are quite a number of files which originated elsewhere, and have their own coding conventions; please conform to the local one, in whichever files you are at work.

1. WinMerge itself uses Microsoft MFC style coding.

   - Code indents are purely tabs.
   - Curly braces are on their own line, indented at the level of the outer code, and code inside the braces is indented one further level.
   - Class member variables are usually prefixed with `m_`.

2. Crystal Text Editor (`WinMerge/editlib/*`) and diffutils code (`io.c`, `normal.c`, `util.c`) use traditional Unix style coding. `analyze.c` should be in this format, but we have made a mess of it :(

   - Code indents are spaces, with tabs used to abbreviate eight consecutive spaces.
   - Curly braces are on their own line, indented two spaces, and then the code inside the curly braces is indented an additional two spaces.

### Doxygen comments

We have adopted doxygen style as our desired commenting style for functions, classes, files, and so forth, in WinMerge code (this applies only to native WinMerge code, not imported files).

- We're using JavaDoc style comments.
- It is probably easiest to simply imitate existing examples. The functions in `DiffThread.cpp` are fully doxygen commented (TODO: it would be better to give a class example, if anyone knows a fully doxygen commented class).
- There is ready to use doxygen config file in `docs/developers/doxygen.cfg`

### RCS Ids

We have adopted the convention of using RCS id lines near the top of our source files (following the doxygen file header comments). Merely add these two lines to any new file you add to the repository, and cvs will modify the Id line by appending file version and date information at every checkin:

    // RCS ID line follows -- this is updated by CVS
    // $Id$

### File release numbers

We are trying to keep a consistent numbering scheme on our file releases, so everybody can figure out what we have released by just looking at the release number. However, some of our older releases do not follow this scheme.

    2.1.2.0
    | | | |
    | | | `------- This number increases for each experimental,
    | | |          and it is reset after each beta or major release.
    | | `--------- Denotes a beta release, an experimental release
    | |            or a minor bug fix of a major release.
    | |              even numbers means "stable" (i.e. a beta).
    | |              odd numbers means "unstable" (i.e. an experimental).
    | `----------- Denotes a major release.
    |                even numbers means "stable".
    |                odd numbers means "unstable".
    `------------- Denotes a major release with major changes.

In this case:

- The next experimental release will have the number 2.1.3.0 (and then 2.1.3.1 and then 2.1.3.2 and so on)
- The next beta release will have the number 2.1.4.0
- The next major release will have the number 2.2.0.0

And if we decide to rewrite most of the code, the next major release will have the number 3.0.0.0

### Packaging file releases

On SourceForge there is some space to put in Release Notes and Change Notes. For experimental releases make sure to put in a note stating what you would like people to test in this release, and a note telling people that this is indeed experimental, so they should not expect everything to work perfectly. For beta builds we paste in all the changes since the last beta release, so that people can see exactly what changed. For major releases, we paste in the list of changes since the last major release, and this list can become very long.

We are using InnoSetup to make an installer with WinMerge. This installer is only used for major releases, for other releases we just zip up these files:

- `WinMerge.exe` and `WinMergeU.exe`
- `ShellExtension.dll` and `register.bat` to register it
- All filters from the `filters/` directory
- All plugins from the `plugins/dlls/` directory. Create a `MergePlugins/` directory and copy the plugins to it
- All `*.lang` files (currently we have 21 languages, counting both Chinese versions)

Please remember to put the version number into both executables. You may use any of the following three methods at least.

1. You may run Src/SetResourceVersions.bat, which will prompt for the new version number, and set it both in Merge.rc and in all the translated rc files.
2. You may use StampVer to stamp the version number into the executables after they are compiled; Christian is familiar with this process.
3. You may also use the old-fashioned process of simply copying all the sources, changing the `Merge.rc` in the copy using the MSVC6 resource editor, and compiling that (many releases have been made in this manual, low-tech fashion).

Whatever method you use, please double-check the executable version numbers before uploading and releasing them.

Now that 2.4 release has translations for Shell Extension we must also carefully version it. If we don't update version number installer won't install updated version. There are no scripts or other tools to update version number, it must be done by hand to `ShellExtension.rc` file (make sure you update all four numbers!). Version numbers follow the rule:

    1.6.1.0
    | | | |
    | | | `------- Not used - 0 (or your own build version?)
    | | `--------- Translation updates or other minor changes increase this by one
    | `----------- New features, bug fixes and other changes affecting to behavior
    |                increase this number by one
    `------------- Denotes a major release with major changes.

- Make sure that version number is updated every time you do a new release!
- If there are only small changes not affecting behaviour or translation updates
  - increase 3rd number by one
- If there's been new features, bug fixes or other non-minor changes
  - increase 2nd number by one

Filenames in file releases follow this standard:

- `WinMerge-2.1.6.0-exe.zip`
- `WinMerge-2.1.6.0-src.zip`
- `WinMerge-2.1.6.0-Setup.exe`

That is, dots are used only inside the version number and before the final extension.

### Tagging CVS when releasing files

When we make a release we always put a note in `readme.txt` in CVS.

It is recommended to put a tag in CVS when you make a file release, because that makes it easier to pull a release version when there were code updates before and after it on the same day (because SourceForge doesn't record time of day correctly, and anyway, it it easier to just ask for a tag).

The tag should follow the same numbering scheme as used above, with the dots replaced by underscores and prefixed with an `R`, so the example experimental above would have a tag named `R2_1_3_0`, the next beta would be named `R2_1_4`, and the next major release would be named `R2_2`.

### Localization : resources files

`WinMerge.exe` and `WinMergeU.exe` are always compiled with the english resources. Custom languages are in separate dll files with extension `.lang`, to be placed in WinMerge directory. Language may be changed dynamically through the menu.

WinMerge localization is achieved through localization of resources (files with extension `.rc`). Actually there is only one rc file in the project, `Merge.rc`. Localized versions for this file are to be stored in the `Languages/` directory, in the subdirectory created for that language.

Besides the resources files you could also translate things like the installer (the ISL files are just INI files) and the readme files (at the moment RTF files).

#### Tips for developers :

- The code must use resource strings for all messages, or displayed text (column title ...).

- Strings ID: when applying a patch, you may define new strings (with as ID the first free ID). But probably you wrote your patch from an old version, and someone may have already inserted a patch for this ID. You need to adapt the ID in resource.h to avoid overlapping ID.

- Strings order: that is really annoying with MSVC. It is important to keep the order of strings unchanged, because merging rc files with WinMerge is then a lot easier. Strings are grouped in block according to their ID masked by `0xFFF0`. So there are at most 16 strings in a block, but maybe less. MSVC reorders strings between and inside blocks, but never reorder blocks (when a new blocks is created, MSVC always put it at the last position).

  Typical method to merge strings in a `Merge.rc` from a patch with a `Merge.rc` in CVS :

  1. Add your new strings with WinMerge : `resource.h` for ID, and `Merge.rc`.
  2. If no overlapping ID, you are finished.
  3. Update your ID in `resource.h`.
  4. Open your resource file in MSVC. Force compilation (I just change a string twice, add a space, delete this space, then save). So MSVC classes new strings in blocks (possibly creating new blocks) according to the ID updated in 3.

  Note: Blocks are not really ordered (there order comes from history), it is not a problem as MSVC never reorders blocks after creation. If you use another tool to change resources, please make sure that the blocks order is unchanged.

- Localized resources must be updated regularly with new resources from `Merge.rc`. Older localized dll may crash with a recent version of WinMerge (missing dialogs). See below...

#### Tips for translators :

- Do not move around things in resource files (MSVC or WinMerge are OK, but maybe you'll use other tools).
- First translation: the order of blocks is different in 2.0 and 2.1 (bug). You have to reorder the blocks if you build your 2.1 localization from your 2.0 one.
- You may localize the layout. Avoid to localize the alignment flag, rather change coordinates.

Please try to avoid changing dialog layout when translating. The layout should be shared by all translations as much as possible, to make merging (and future translation changes) easier. You can of course make controls wider to fit longer texts, but you should not move buttons and other controls if not really necessary.
If you want to improve dialog layout (we welcome UI improvements) you should submit it as src/Merge.rc patch so it will be merged to all translations.

#### Compiling

We have a customised tool for compiling language files. Project for it is in CVS:

    /WinMerge/MakeResDll

When that project is compiled, it produces `MakeResDll.exe`. Copy that executable to `/WinMerge/Src/Languages/`. In that directory there are already some batch-files which can now be used to compile language files:

`BuildAll.bat`
  compiles all languages in `/WinMerge/Src/Languages/`
`BuildDll.bat <lang>`
  compiles given language
`CopyAll.bat`
  copies compiled lang files to build directories
`UpdateAll_resource_h.bat`
  copies `resource.h` file from `/WinMerge/Src/` to language directories. Handy when merging language changes.

Compiled language files (`*.lang`) are placed in `/WinMerge/Src/Languages/Dll` .

##### Forcing compiler version with MakeResDll

If MakeResDll does not work, and you wish to force it to use the compiler (resource compiler and linker) of your choice, there are registry settings to accomplish this. Perry added these because he has been unable to get MakeResDll link successfully using VS.NET 2003, due to it failing to find `mspdb71.dll` at runtime. To force use of the Visual C++ 6 binaries, assuming Visual C++ 6 is correctly installed, set

    HKEY_CURRENT_USER\Software\Thingamahoochie\MakeResDll\Settings\VcVersion="6"

### Localization : merging and scheduling

#### Issues :

- It is slow and tedious to update 21 languages for just one patch. But reducing the frequency of such updates does not help either: 5 small updates are tedious and frequent, but easy; 1 big update is more infrequent, but much more tedious and difficult.

- Merging of layout: translator may change layout, then when developers insert new controls, moved and new controls may overlap. Visual check of 21 dialogs is definitively too long for a single patch update.

- Delays in localization: translators generally need some weeks to translate, so their version is already outdated when the localization is complete, and merging with CVS must be done again.

#### Global rules for localized resource files :

- Translators localize just betas or releases. They don't localize CVS or experimentals (they don't have to, they may if they will, then they do the merging themselves).

- Patches: developers update the files : add new items, remove deleted ones, move moved items (controls going from one dialog to another one). No care of layout or visual check of dialogs. With such updates, languages dll are valid (no crash).

  We may reduce this work to the languages used by experimental testers (and, for other languages, for the next beta/release, reapply together all patches since the last beta/release localization).

- Good synchronization is required between developers and translators for the latest beta/release. For older versions, translators are free. The latest beta/release is the latest build which is either a beta or either a release.

- Developers do not change resources for beta/release after their creation. Only localization/layout changes may be applied.

#### Typical steps for a new beta/release :

1. Layout of dialogs. Visual check. Probably a developer work (for speed, and maybe the language has no more translator). Update the CVS after this step.
2. Branch the localized resource for the beta/release. Build the dll.
3. Beginning of localization. The translators gets the localized resource.
4. ...
5. Translator applies his localization to the branch. Rebuild the dll.
6. CVS localization. Developers merge the changes from 4 to the current CVS. The layout may be merged only partially, as anyway it will be checked for the next beta/release.

Steps 3, 4, 5, 6 may be reproduced. As long as the impacted beta/release is the last one, step 6 is necessary (or the changes will be lost in the next beta/release). But step 6 is done by developers only once (per language and per beta/release), after it is the translator's job. Please localize once and well rather than in small chunks!

#### Merging tools for resources :

WinMerge of course, plus the plugin `RCLocalizationHelper.dll`.

Most text/layout differences are ignored, so new/deleted/moved items appears clearly. Help to merge patches, and to merge a newly localized resource to its CVS version (apply the CVS changes to the newly localized resource). Contrary to a lot of (bad) localization tools, this method preserves the layout done by the translator. There are good localization tools however, and we will welcome with pleasure anyone with such a tool in the project.

### Logging

Logs are a good tool for tracing errors. But logs must be first written. Its always a good habit to write error message to logfile also.

#### Writing to log:

Simplest way to write errormessage to log is using `void LogErrorString(LPCTSTR sz)` defined in `stdafx.h`. Another way is to directly use `gLog` which is global instance of `CLogFile`. Log is written to users temporary directory (`$temp`) with name `WinMerge.log`.

#### Enabling/disabling log writing

Log writing is controlled by registry value:

    HKEY_CURRENT_USER\Software\Thingamahoochie\WinMerge\Settings\Logging

Possible values are:

- 0 - no logging
- 1 - all logging enabled
- 2 - only errormessages and warnings written to log

### Shell Extension

WinMerge sets executable path (`WinMerge.exe`) which shellextension starts every time when options-dialog is closed. This can cause problems when testing several versions of WinMerge. There is registry value to overwrite path to WinMerge executable:

    HKEY_CURRENT_USER\Software\Thingamahoochie\WinMerge\PriExecutable

It does not exist by default, so create `PriExecutable` as string value and type path of `WinMerge.exe` you mainly use as its value. If this value exists ShellExtension does not care about another path value.