This file is licensed under the terms of the expat license, see the file EXPAT.

+ Hacking guide for Midori +

- How to contribute
- Coding style
- Source files in the project
- Examplary source code

+++ How to contribute +++

There are several ways to contribute to the project:

For translating, have a look at the file TRANSLATE.

For helping with testing and triaging bug reports, you should register with the bug tracker at https://bugs.launchpad.net/midori and join #midori on irc.freenode.net where a lot of problems are discussed. You can start right away by trying to reproduce bug reports and comment with your findings.

If you are interested in contributing code, there are a few options. You can join #midori to discuss a particular problem you would like to look into, or a feature you would want to implement. Opening a bug report or feature request if there isn't already one is the next step. To attract some attention, if you attached a patch or have questions, ask in #midori.

+++ Coding style +++

Indentation is 4 spaces, no tabs, preferrably at 80 to 120 columns per line to
avoid automated line-breaks. Trailing whitespace is not desirable.

Declarations go to the beginning of a block, not inline. Variables of one plain
type may be grouped in one declaration, pointer types may not be grouped. The
asterisk goes next to the type.
Variables should be ordered in the order they are used.

Comments explain functionality, they should not state facts. The appropriate
style is always C style /* */, not C++ style.

Variable and function names should be animal, animal_shelter or animalsc in
case it would otherwise be very long. Loop counters may be single letters.
Type names should be Animal, AnimalShelter or AnimalSC. No prefixes from third
party projects should be used, such as GTK or WebKit, while underlines may be
used but do not have a particular meaning.

There is a space between functions or keywords and round brackets, and curly
brackets always go on separate lines, at the indentation level of the
function, conditional or loop expression. Curly brackets are left out for single
statement conditionals and loops unless they notably help readability.
The type of a function goes on a separate line before the function.
Preprocessor instructions are indented with the code they relate to.

Code history is precious, so one should avoid renaming a lot of functions at
once or moving whole paragraphs only to add or remove a level of indentation.
Moving blocks of code around is also undesriable because it makes patches less
readable since the result looks like new code.


+++ Source files in the project +++

Core:
    Files prefixed with "midori-" in the folder "midori" make up the core. They
    are essential to running the browser and mostly tailored to the browser.
    All header files prefixed with "midori-" are considered supported API and
    can be used to implement extensions.
    "sokoke" is a collection of very specialized helper functions which change
    from time to time as needed. In the past some of the code was moved to
    "katze" when it was considered generally useful.
    "socket" is a socket implementation with no dependency on other parts of
    the core, which is used if Midori is built without an external single
    instance support library.
Panels:
    Files in the "panels" folder are classes that implement MidoriViewable and
    which are loaded into the MidoriPanel at startup. These panels are in
    principle optional.
Katze:
    Re-usable classes and utility functions that don't depend on the core and
    some of that code indeed found its way into other projects.
Extensions:
    These are extensions, written in C, which are loaded optionally if the user
    so chooses. Extensions can use API from "midori-" and "katze-" headers. Each
    module consists of either a single .c file or a folder with .c files.
Tests:
    Unit tests are run regularly to verify possible regressions or measure
    performance of implementations. Except for select cases code changes should
    not cause failure of unit tests.


+++ Examplary source code +++

    /*
       Copyright
       LICENSE TEXT
    */

    #include "foo.h"

    #include "bar.h"

    #include <glib.h>

    void
    foobar (FooEnum bar, const gchar* foo)
    {
        gint n, i;

        if (!foo)
            return;

        #ifdef BAR_STRICT
        if (bar == FOO_N)
        {
            g_print ("illegal value for 'bar'.\n");
            return;
        }
        #endif

        /* this is an example */
        switch (bar)
        {
        case FOO_FOO:
            n = bar + 1;
            break;
        case FOO_BAR:
            n = bar + 10;
            break;
        default:
            n = 1;
        }

        for (i = 0; i < n; i++)
        {
            g_print ("%s\n", foo);
        }
    }

Header file example:

    /*
       Copyright
       LICENSE TEXT
    */

    #ifndef __FOO_H__
    #define __FOO_H__ 1

    #ifdef HAVE_BAR_H
        #define BAR_STRICT
    #endif

    /* Types */

    typedef enum
    {
        FOO_FOO,
        FOO_BAR,
        FOO_N
    } FooEnum;

    typedef struct
    {
        FooEnum foo_bar;
    } FooStruct;

    /* Declarations */

    void
    foo_bar           (FooEnum      bar,
                       const gchar* foo);

    const gchar*
    foo_foo           (FooStruct foo_struct,
                       guint     number,
                       gboolean  flag);

    #endif /* !__FOO_H__ */
