Coding Practice
This chapter describes the relevant coding practices in Wine,
that you should be aware of before doing any serious development
in Wine.
Patch Format
Patches are submitted via email to the Wine patches mailing
list, wine-patches@winehq.org. Your patch
should include:
A meaningful subject (very short description of patch)
A long (paragraph) description of what was wrong and what
is now better. (recommended)
A change log entry (short description of what was
changed).
The patch in diff -u format
cvs diff -u works great for the common case
where a file is edited. However, if you add or remove a file
cvs diff will not report that correctly so
make sure you explicitly take care of this rare case.
For additions simply include them by appending the
diff -u /dev/null /my/new/file output of
them to any cvs diff -u output you may
have. Alternatively, use diff -Nu olddir/
newdir/ in case of multiple new files to add.
For removals, clearly list the files in the description of the
patch.
Since wine is constantly changing due to development it is
strongly recommended that you use cvs for patches, if you
cannot use cvs for some reason, you can submit patches against
the latest tarball. To do this make a copy of the files that
you will be modifying and diff -u against
the old file. I.E.
diff -u file.old file.c > file.txt
Some notes about style
There are a few conventions about coding style that have
been adopted over the years of development. The rational for
these rules
is explained for each one.
No HTML mail, since patches should be in-lined and HTML
turns the patch into garbage. Also it is considered bad
etiquette as it uglifies the message, and is not viewable
by many of the subscribers.
Only one change set per patch. Patches should address only
one bug/problem at a time. If a lot of changes need to be
made then it is preferred to break it into a series of
patches. This makes it easier to find regressions.
Tabs are not forbidden but discouraged. A tab is defined
as 8 characters and the usual amount of indentation is 4
characters.
C++ style comments are discouraged since some compilers
choke on them.
Commenting out a block of code is usually done by
enclosing it in #if 0 ... #endif
Statements. For example.
/* note about reason for commenting block */
#if 0
code
code /* comments */
code
#endif
The reason for using this method is that it does not
require that you edit comments that may be inside the
block of code.
Patches should be in-lined (if you can configure your
email client to not wrap lines), or attached as plain text
attachments so they can be read inline. This may mean some
more work for you. However it allows others to review your
patch easily and decreases the chances of it being
overlooked or forgotten.
Code is usually limited to 80 columns. This helps prevent
mailers mangling patches by line wrap. Also it generally
makes code easier to read.
If the patch fixes a bug in Bugzilla please provide a link
to the bug in the comments of the patch. This will make it
easier for the maintainers of Bugzilla.
Inline attachments with Outlook Express
Outlook Express is notorious for mangling
attachments. Giving the patch a .txt
extension and attaching will solve the problem for most
mailers including Outlook. Also, there is a way to enable
Outlook Express to send .diff
attachments.
You need the following two things to make it work.
Make sure that .diff files have
\r\n line ends, because if OE detects that there is no
\r\n line endings it switches to quoted-printable format
attachments.
Using regedit add key "Content Type"
with value "text/plain" to the
.diff extension under
HKEY_CLASSES_ROOT (same as for .txt
extension). This tells OE to use
Content-Type: text/plain instead of
application/octet-stream.
Item #1 is important. After you hit the "Send" button, go to
"Outbox" and using "Properties" verify the message source to
make sure that the mail has the correct format. You might want
to send several test emails to yourself too.
Alexandre's Bottom Line
The basic rules are: no attachments, no MIME crap, no
line wrapping, a single patch per mail. Basically if I can't
do "cat raw_mail | patch -p0" it's in the
wrong format.
Quality Assurance
(Or, "How do I get Alexandre to apply my patch quickly so I
can build on it and it will not go stale?")
Make sure your patch applies to the current CVS head
revisions. If a bunch of patches are committed to CVS that may
affect whether your patch will apply cleanly then verify that
your patch does apply! cvs update is your
friend!
Save yourself some embarrassment and run your patched code
against more than just your current test example. Experience
will tell you how much effort to apply here. If there are
any conformance tests for the code you're working on, run them
and make sure they still pass after your patch is applied. Running
tests can be done by running make test. You may
need to run make testclean to undo the results
of a previous test run. See the testing
guide for
more details on Wine's conformance tests.
Porting Wine to new Platforms
This document provides a few tips on porting Wine to your
favorite (UNIX-based) operating system.
Why #ifdef MyOS is probably a mistake.
Operating systems change. Maybe yours doesn't have the
foo.h header, but maybe a future
version will have it. If you want to #include
<foo.h>, it doesn't matter what operating
system you are using; it only matters whether
foo.h is there.
Furthermore, operating systems change names or "fork" into
several ones. An #ifdef MyOs will break
over time.
If you use the feature of autoconf -- the
Gnu auto-configuration utility -- wisely, you will help
future porters automatically because your changes will test
for features, not names of operating
systems. A feature can be many things:
existence of a header file
existence of a library function
existence of libraries
bugs in header files, library functions, the compiler, ...
You will need Gnu Autoconf, which you can get from your
friendly Gnu mirror. This program takes Wine's
configure.ac file and produces a
configure shell script that users use
to configure Wine to their system.
There are exceptions to the "avoid
#ifdef MyOS" rule. Wine, for example, needs
the internals of the signal stack -- that cannot easily be
described in terms of features. Moreover, you can not use
autoconf's HAVE_*
symbols in Wine's headers, as these may be used by Winelib
users who may not be using a configure
script.
Let's now turn to specific porting problems and how to solve
them.
MyOS doesn't have the foo.h header!
This first step is to make autoconf check
for this header. In configure.in you
add a segment like this in the section that checks for
header files (search for "header files"):
AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
If your operating system supports a header file with the
same contents but a different name, say
bar.h, add a check for that also.
Now you can change
#include <foo.h>
to
#ifdef HAVE_FOO_H
#include <foo.h>
#elif defined (HAVE_BAR_H)
#include <bar.h>
#endif
If your system doesn't have a corresponding header file even
though it has the library functions being used, you might
have to add an #else section to the
conditional. Avoid this if you can.
You will also need to add #undef HAVE_FOO_H
(etc.) to include/config.h.in
Finish up with make configure and
./configure.
MyOS doesn't have the bar function!
A typical example of this is the memmove
function. To solve this problem you would add
memmove to the list of functions that
autoconf checks for. In
configure.in you search for
AC_CHECK_FUNCS and add
memmove. (You will notice that someone
already did this for this particular function.)
Secondly, you will also need to add
#undef HAVE_BAR to
include/config.h.in
The next step depends on the nature of the missing function.
Case 1:
It's easy to write a complete implementation of the
function. (memmove belongs to
this case.)
You add your implementation in
misc/port.c surrounded by
#ifndef HAVE_MEMMOVE and
#endif.
You might have to add a prototype for your function.
If so, include/miscemu.h might be
the place. Don't forget to protect that definition by
#ifndef HAVE_MEMMOVE and
#endif also!
Case 2:
A general implementation is hard, but Wine is only
using a special case.
An example is the various wait
calls used in SIGNAL_child from
loader/signal.c. Here we have a
multi-branch case on features:
#ifdef HAVE_THIS
...
#elif defined (HAVE_THAT)
...
#elif defined (HAVE_SOMETHING_ELSE)
...
#endif
Note that this is very different from testing on
operating systems. If a new version of your operating
systems comes out and adds a new function, this code
will magically start using it.
Finish up with make configure and
./configure.
Adding New Languages
This file documents the necessary procedure for adding a new
language to the list of languages that Wine can display system
menus and forms in. Adding new translations is not hard as it
requires no programming knowledge or special skills.
Language dependent resources reside in files
named somefile_Xx.rc or
Xx.rc, where Xx
is your language abbreviation (look for it in
include/winnls.h). These are included
in a master file named somefile.rc or
rsrc.rc, located in the same
directory as the language files.
To add a new language to one of these resources you
need to make a copy of the English resource (located
in the somefile_En.rc file) over to
your somefile_Xx.rc file, include this
file in the master somefile.rc file,
and edit the new file to translate the English text.
You may also need to rearrange some of the controls
to better fit the newly translated strings. Test your changes
to make sure they properly layout on the screen.
In menus, the character "&" means that the next
character will be highlighted and that pressing that
letter will select the item. You should place these
"&" characters suitably for your language, not just
copy the positions from English. In particular,
items within one menu should have different highlighted
letters.
To get a list of the files that need translating,
run the following command in the root of your Wine tree:
find -name "*En.rc".
When adding a new language, also make sure the parameters
defined in ./dlls/kernel/nls/*.nls
fit your local habits and language.