  <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:&nbsp;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
	  &lt;foo.h&gt;</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 &lt;foo.h&gt;
      </programlisting>
      <para>
	to
      </para>
      <programlisting>
#ifdef HAVE_FOO_H
#include &lt;foo.h&gt;
#elif defined (HAVE_BAR_H)
#include &lt;bar.h&gt;
#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 "&amp;" means that the next
      character will be highlighted and that pressing that
      letter will select the item. You should place these
      "&amp;" 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:
-->
