| <chapter id="codingpractice"> |
| <title>Coding Practice</title> |
| |
| <para> |
| This chapter describes the relevant coding practices in Wine, |
| that you should be aware of before doing any serious development |
| in Wine. |
| </para> |
| <sect1 id="patch-format"> |
| <title>Patch Format</title> |
| |
| <para> |
| Patches are submitted via email to the Wine patches mailing |
| list, <email>wine-patches@winehq.org</email>. Your patch |
| should include: |
| </para> |
| |
| <itemizedlist> |
| <listitem> |
| <para> |
| A meaningful subject (very short description of patch) |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| A long (paragraph) description of what was wrong and what |
| is now better. (recommended) |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| A change log entry (short description of what was |
| changed). |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| The patch in <command>diff -u</command> format |
| </para> |
| </listitem> |
| </itemizedlist> |
| |
| <para></para> |
| |
| <para> |
| <command>cvs diff -u</command> works great for the common case |
| where a file is edited. However, if you add or remove a file |
| <command>cvs diff</command> will not report that correctly so |
| make sure you explicitly take care of this rare case. |
| </para> |
| <para> |
| For additions simply include them by appending the |
| <command>diff -u /dev/null /my/new/file</command> output of |
| them to any <command>cvs diff -u</command> output you may |
| have. Alternatively, use <command>diff -Nu olddir/ |
| newdir/</command> in case of multiple new files to add. |
| </para> |
| <para> |
| For removals, clearly list the files in the description of the |
| patch. |
| </para> |
| <para> |
| 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 <command>diff -u</command> against |
| the old file. I.E. |
| </para> |
| <screen> |
| diff -u file.old file.c > file.txt |
| </screen> |
| </sect1> |
| |
| <sect1 id="Style-notes"> |
| <title>Some notes about style</title> |
| |
| <para> |
| There are a few conventions that about coding style that have |
| been adopted over the years of development. The rational for |
| these <quote>rules</quote> is explained for each one. |
| </para> |
| <itemizedlist> |
| <listitem> |
| <para> |
| 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. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| 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. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Tabs are not forbidden but discouraged. A tab is defined |
| as 8 characters and the usual amount of indentation is 4 |
| characters. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| C++ style comments are discouraged since some compilers |
| choke on them. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Commenting out a block of code is usually done by |
| enclosing it in <command>#if 0 ... #endif</command> |
| Statements. For example. |
| </para> |
| <screen> |
| /* note about reason for commenting block */ |
| #if 0 |
| code |
| code /* comments */ |
| code |
| #endif |
| </screen> |
| <para> |
| The reason for using this method is that it does not |
| require that you edit comments that may be inside the |
| block of code. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| 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. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Code is usually limited to 80 columns. This helps prevent |
| mailers mangling patches by line wrap. Also it generally |
| makes code easier to read. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| 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. |
| </para> |
| </listitem> |
| </itemizedlist> |
| <sect2 id="Inline-Attachments-with-OE"> |
| <title>Inline attachments with Outlook Express</title> |
| <para> |
| Outlook Express is notorious for mangling |
| attachments. Giving the patch a <filename>.txt</filename> |
| extension and attaching will solve the problem for most |
| mailers including Outlook. Also, there is a way to enable |
| Outlook Express send <filename>.diff</filename> |
| attachments. |
| </para> |
| <para> |
| You need following two things to make it work. |
| </para> |
| <orderedlist> |
| <listitem> |
| <para> |
| Make sure that <filename>.diff</filename> 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. |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| Using regedit add key "Content Type" |
| with value "text/plain" to the |
| <filename>.diff</filename> extension under |
| HKEY_CLASSES_ROOT (same as for <filename>.txt</filename> |
| extension). This tells OE to use |
| Content-Type: text/plain instead of |
| application/octet-stream. |
| </para> |
| </listitem> |
| </orderedlist> |
| <para> |
| Item #1 is important. After you hit "Send" button, go to |
| "Outbox" and using "Properties" verify the message source to |
| make sure that the mail has correct format. You might want |
| to send several test emails to yourself too. |
| </para> |
| </sect2> |
| <sect2 id="Alexandre-Bottom-Line"> |
| <title>Alexandre's Bottom Line</title> |
| <para> |
| <quote>The basic rules are: no attachments, no MIME crap, no |
| line wrapping, a single patch per mail. Basically if I can't |
| do <command>"cat raw_mail | patch -p0"</command> it's in the |
| wrong format.</quote> |
| </para> |
| </sect2> |
| </sect1> |
| |
| <sect1 id="patch-quality"> |
| <title>Quality Assurance</title> |
| |
| <para> |
| (Or, "How do I get Alexandre to apply my patch quickly so I |
| can build on it and it will not go stale?") |
| </para> |
| <para> |
| 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! <command>cvs update</command> is your |
| friend! |
| </para> |
| <para> |
| 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 <command>make test</command>. You may |
| need to run <command>make testclean</command> to undo the results |
| of a previous test run. See the <quote>testing</quote> guide for |
| more details on Wine's conformance tests. |
| </para> |
| |
| </sect1> |
| <sect1 id="porting"> |
| <title>Porting Wine to new Platforms</title> |
| <para> |
| This document provides a few tips on porting Wine to your |
| favorite (UNIX-based) operating system. |
| </para> |
| |
| <sect2> |
| <title> |
| Why <symbol>#ifdef MyOS</symbol> is probably a mistake. |
| </title> |
| |
| <para> |
| Operating systems change. Maybe yours doesn't have the |
| <filename>foo.h</filename> header, but maybe a future |
| version will have it. If you want to <symbol>#include |
| <foo.h></symbol>, it doesn't matter what operating |
| system you are using; it only matters whether |
| <filename>foo.h</filename> is there. |
| </para> |
| <para> |
| Furthermore, operating systems change names or "fork" into |
| several ones. An <symbol>#ifdef MyOs</symbol> will break |
| over time. |
| </para> |
| <para> |
| If you use the feature of <command>autoconf</command> -- the |
| Gnu auto-configuration utility -- wisely, you will help |
| future porters automatically because your changes will test |
| for <emphasis>features</emphasis>, not names of operating |
| systems. A feature can be many things: |
| </para> |
| |
| <itemizedlist> |
| <listitem> |
| <para> |
| existence of a header file |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| existence of a library function |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| existence of libraries |
| </para> |
| </listitem> |
| <listitem> |
| <para> |
| bugs in header files, library functions, the compiler, ... |
| </para> |
| </listitem> |
| </itemizedlist> |
| <para> |
| You will need Gnu Autoconf, which you can get from your |
| friendly Gnu mirror. This program takes Wine's |
| <filename>configure.ac</filename> file and produces a |
| <filename>configure</filename> shell script that users use |
| to configure Wine to their system. |
| </para> |
| <para> |
| There <emphasis>are</emphasis> exceptions to the "avoid |
| <symbol>#ifdef MyOS</symbol>" 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 |
| <filename>autoconf</filename>'s <symbol>HAVE_*</symbol> |
| symbols in Wine's headers, as these may be used by Winelib |
| users who may not be using a <filename>configure</filename> |
| script. |
| </para> |
| <para> |
| Let's now turn to specific porting problems and how to solve |
| them. |
| </para> |
| </sect2> |
| |
| <sect2> |
| <title> |
| MyOS doesn't have the <filename>foo.h</filename> header! |
| </title> |
| |
| <para> |
| This first step is to make <command>autoconf</command> check |
| for this header. In <filename>configure.in</filename> you |
| add a segment like this in the section that checks for |
| header files (search for "header files"): |
| </para> |
| <programlisting> |
| AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H)) |
| </programlisting> |
| <para> |
| If your operating system supports a header file with the |
| same contents but a different name, say |
| <filename>bar.h</filename>, add a check for that also. |
| </para> |
| <para> |
| Now you can change |
| </para> |
| <programlisting> |
| #include <foo.h> |
| </programlisting> |
| <para> |
| to |
| </para> |
| <programlisting> |
| #ifdef HAVE_FOO_H |
| #include <foo.h> |
| #elif defined (HAVE_BAR_H) |
| #include <bar.h> |
| #endif |
| </programlisting> |
| <para> |
| 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 <symbol>#else</symbol> section to the |
| conditional. Avoid this if you can. |
| </para> |
| <para> |
| You will also need to add <symbol>#undef HAVE_FOO_H</symbol> |
| (etc.) to <filename>include/config.h.in</filename> |
| </para> |
| <para> |
| Finish up with <command>make configure</command> and |
| <command>./configure</command>. |
| </para> |
| </sect2> |
| |
| <sect2> |
| <title> |
| MyOS doesn't have the <function>bar</function> function! |
| </title> |
| |
| <para> |
| A typical example of this is the <function>memmove</function> |
| function. To solve this problem you would add |
| <function>memmove</function> to the list of functions that |
| <command>autoconf</command> checks for. In |
| <filename>configure.in</filename> you search for |
| <function>AC_CHECK_FUNCS</function> and add |
| <function>memmove</function>. (You will notice that someone |
| already did this for this particular function.) |
| </para> |
| <para> |
| Secondly, you will also need to add |
| <symbol>#undef HAVE_BAR</symbol> to |
| <filename>include/config.h.in</filename> |
| </para> |
| <para> |
| The next step depends on the nature of the missing function. |
| </para> |
| |
| <variablelist> |
| <varlistentry> |
| <term>Case 1:</term> |
| <listitem> |
| <para> |
| It's easy to write a complete implementation of the |
| function. (<function>memmove</function> belongs to |
| this case.) |
| </para> |
| <para> |
| You add your implementation in |
| <filename>misc/port.c</filename> surrounded by |
| <symbol>#ifndef HAVE_MEMMOVE</symbol> and |
| <symbol>#endif</symbol>. |
| </para> |
| <para> |
| You might have to add a prototype for your function. |
| If so, <filename>include/miscemu.h</filename> might be |
| the place. Don't forget to protect that definition by |
| <symbol>#ifndef HAVE_MEMMOVE</symbol> and |
| <symbol>#endif</symbol> also! |
| </para> |
| </listitem> |
| </varlistentry> |
| <varlistentry> |
| <term>Case 2:</term> |
| <listitem> |
| <para> |
| A general implementation is hard, but Wine is only |
| using a special case. |
| </para> |
| <para> |
| An example is the various <function>wait</function> |
| calls used in <function>SIGNAL_child</function> from |
| <filename>loader/signal.c</filename>. Here we have a |
| multi-branch case on features: |
| </para> |
| <programlisting> |
| #ifdef HAVE_THIS |
| ... |
| #elif defined (HAVE_THAT) |
| ... |
| #elif defined (HAVE_SOMETHING_ELSE) |
| ... |
| #endif |
| </programlisting> |
| <para> |
| 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. |
| </para> |
| </listitem> |
| </varlistentry> |
| </variablelist> |
| <para> |
| Finish up with <command>make configure</command> and |
| <command>./configure</command>. |
| </para> |
| </sect2> |
| </sect1> |
| |
| <sect1 id="adding-languages"> |
| <title>Adding New Languages</title> |
| |
| <para> |
| 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. |
| </para> |
| |
| <para> |
| Language dependent resources reside in files |
| named <filename>somefile_Xx.rc</filename> or |
| <filename>Xx.rc</filename>, where <literal>Xx</literal> |
| is your language abbreviation (look for it in |
| <filename>include/winnls.h</filename>). These are included |
| in a master file named <filename>somefile.rc</filename> or |
| <filename>rsrc.rc</filename>, located in the same |
| directory as the language files. |
| </para> |
| |
| <para> |
| To add a new language to one of these resources you |
| need to make a copy of the English resource (located |
| in the <filename>somefile_En.rc</filename> file) over to |
| your <filename>somefile_Xx.rc</filename> file, include this |
| file in the master <filename>somefile.rc</filename> 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. |
| </para> |
| |
| <para> |
| 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. |
| </para> |
| |
| <para> |
| To get a list of the files that need translating, |
| run the following command in the root of your Wine tree: |
| <command>find -name "*En.rc"</command>. |
| </para> |
| |
| <para> |
| When adding a new language, also make sure the parameters |
| defined in <filename>./dlls/kernel/nls/*.nls</filename> |
| fit your local habits and language. |
| </para> |
| </sect1> |
| </chapter> |
| |
| <!-- Keep this comment at the end of the file |
| Local variables: |
| mode: sgml |
| sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "") |
| End: |
| --> |