VICE project coding guidelines
==============================

This document is intended to set some guidelines for people wanting to
contribute code to the VICE project.

There are two distinct parts to the VICE source code, the architecture code
parts which are located in src/arch, and the common code parts which are
located everywhere in src except in src/arch.

The architecture code parts are in their own respective directories and may
have their own coding style.

The common code however is used by all supported architectures and therefor
needs to be as portable as possible. To achieve this portability some
guidelines have to be followed.



Cosmetic guidelines for all code
--------------------------------

To keep the code easy to follow please read the following statements:

- No variable declarations after the first line of code, some compilers
  just can't handle it.

- Don't use mixtures of tabs and spaces as indentation, using 4 spaces per
  level will make the code look the same no matter what editor you use.
  When changing an existing file, make sure the indentation style is the
  same throughout the source file.

- For 'if' and 'for' always use braces.
  examples:

    if (foo) {
        ...
    }

    if (foo) {
        ...
    } else {
        ...
    }

    for (i = 0; i < 255; i++) {
        ...
    }

- To give the code a consistent look use specifiers named with prefixes
  like in the following examples:

    struct foobar_s {
        ...
    };
  
    typedef ... foobar_t;

    enum stuff_e {
        ...
    };
  
    union many_u {
        ...
    };
  
  Of course combinations may be used:

    typedef struct foobar_s {
        ...
    } foobar_t;

  Exceptions are basic type like BYTE, WORD, DWORD and code that follows a 
  coding style of a certain architecture, e.g. UI code. 

- Preprocessor macros which define constants or enumeration values should
  be written in capital letters.
  
   #define FORTYTWO 42

   typedef numbers_e {
       NUM_ZERO,
       NUM_ONE
   } numbers_t;

Common code guidelines
----------------------

Many different compilers are used to compile the common code parts.

- When using headers which are tested for in configure.in don't assume they
  exist, use the #ifdef HAVE_*_H instead.

- Don't use C++ style comments (// comment), use C-style comments instead
  (/* comment */).

- When adding header files use VICE_*_H as shown in the following example:

#ifndef VICE_RS232_H
#define VICE_RS232_H

...code...

#endif


intl code guidelines
--------------------

VICE supports intl for win32, amiga and *nix platforms. Any text belonging
that is meant for the user (command-line/UI) needs to be handled by means
of the translation system.

The command-line options structure is defined as followed:

typedef struct cmdline_option_s {
    /* Name of command-line option.  */
    const char *name;

    /* Behavior of this command-line option.  */
    cmdline_option_type_t type;

    /* Flag: Does this option need an argument?  */
    int need_arg;

    /* Function to call if type is `CALL_FUNCTION'.  */
    int (*set_func)(const char *value, void *extra_param);

    /* Extra parameter to pass to `set_func' if type is `CALL_FUNCTION'.  */
    void *extra_param;

    /* Resource to change if `type' is `SET_RESOURCE'.  */
    const char *resource_name;

    /* Value to assign to `resource_name' if `type' is `SET_RESOURCE' and
       `need_arg' is zero.  */
    void *resource_value;

    /* flag to indicate to use the ID instead of the char */
    int use_param_name_id;

    /* flag to indicate to use the ID instead of the char */
    int use_description_id;

    /* ID of the string to display after the option name in the help screen. */
    int param_name_trans;

    /* ID of the description string. */
    int description_trans;

    /* String to display after the option name in the help screen. */
    const char *param_name;

    /* Description string. */
    const char *description;
} cmdline_option_t;


The intl related fields are:

param_name           This field holds a pointer to the string to be used for
                     the parameter of the commandline option, fill in with
                     NULL when ID is used.

description          This field holds a pointer to the string to be used for
                     the description of the commandline option, fill up with
                     NULL when ID is used.


param_name_trans     This field holds the ID of the string to be used for the
                     parameter of the commandline option, fill in with
                     IDCLS_UNUSED when string is used.

description_trans    This field holds the ID of the string to be used for the
                     description of the commandline option, fill in with
                     IDCLS_UNUSED when string is used.


use_param_name_id    This field is used to indicate if an ID or text needs to
                     be used, ID's are normally used for common code, amiga
                     code and win32 code. When set to USE_PARAM_ID the ID
                     field will be used, and when set to USE_PARAM_STRING the
                     text pointer field will be used.

use_description_id   This field is used to indicate if an ID or text needs to
                     be used, ID's are normally used for common code, amiga
                     code and win32 code. When set to USE_DESCRIPTION_ID
                     the ID field will be used, and when set to
                     USE_DESCRIPTION_STRING the text pointer field will be
                     used.


Adding new common code and win32/amiga ui-related elements
----------------------------------------------------------

Easy way:

ui_message(T_("text"))

The T_(...) will indicate to the intl maintainer that this item needs to be
added to the translation system. The intl maintainer will take care of these
and the coder has no extra worries about it.


Hard way:

For any text you add you will need to create a new ID and add the ID to the
ID-list in src/translate.txt and add a translation table block in
src/translate_text.c. There are two types of ID's in the common code IDGS_*
(Global Strings: text used in common code) and IDCLS_* (Command Line Strings:
text used in command-line options).

Example:

you want to add the command-line option text "<example>".

add IDCLS_EXAMPLE to translate.txt
add IDCLS_EXAMPLE text to the translation table in the following form

/* path/file.c */
/* en */ {IDCLS_EXAMPLE,    N_("<example>")},
#ifdef HAS_TRANSLATION
/* de */ {IDCLS_EXAMPLE_DE, ""},  /* fuzzy */
/* fr */ {IDCLS_EXAMPLE_FR, ""},  /* fuzzy */
/* hu */ {IDCLS_EXAMPLE_HU, ""},  /* fuzzy */
/* it */ {IDCLS_EXAMPLE_IT, ""},  /* fuzzy */
/* nl */ {IDCLS_EXAMPLE_NL, ""},  /* fuzzy */
/* pl */ {IDCLS_EXAMPLE_PL, ""},  /* fuzzy */
/* sv */ {IDCLS_EXAMPLE_SV, ""},  /* fuzzy */
#endif


Adding a common code or amiga/win32 command-line option
-------------------------------------------------------

Easy way:

    { "-midiout", SET_RESOURCE, 1,
      NULL, NULL, "MIDIOutDev", NULL,
      USE_PARAM_STRING, USE_DESCRIPTION_STRING,
      IDCLS_UNUSED, IDCLS_UNUSED,
      T_("<name>"), T_("Specify MIDI-Out device") },

The T_(...) will indicate to the intl maintainer that this item needs to be
added to translate.*


Hard way:

    { "-midiout", SET_RESOURCE, 1,
      NULL, NULL, "MIDIOutDev", NULL,
      USE_PARAM_STRING, USE_DESCRIPTION_STRING,
      IDCLS_NAME, IDCLS_SPECIFY_MIDI_OUT_DEVICE,
      NULL, NULL },

You will need to add the IDCLS_NAME and IDCLS_SPECIFY_MIDI_OUT_DEVICE to the
translate files if the ID's don't exist yet.


Adding a common code or amiga/win32 ui_message
----------------------------------------------

Easy way:

ui_message(T_("this is a dialog message"));


Hard way:

ui_message(translate_text(IDGS_THIS_IS_A_DIALOG_MESSAGE));

IDGS_THIS_IS_A_DIALOG_MESSAGE will need to be added to the translate files if
the ID doesn't exist yet.



Adding a *nix command-line option
---------------------------------

For *nix no ID's are used, but it does use the gettext method, so N_(...) is
needed.

    { "-midiout", SET_RESOURCE, 1,
      NULL, NULL, "MIDIOutDev", NULL,
      USE_PARAM_STRING, USE_DESCRIPTION_STRING,
      IDCLS_UNUSED, IDCLS_UNUSED,
      N_("<name>"), N_("Specify MIDI-Out device") },



Adding a *nix ui_message
------------------------

For *nix no ID's are used, but it does use the gettext method, so _(...) is
needed.

ui_message(_("this is a dialog message"));


Adding a command-line option for an architecture other than *nix, amiga or win32
--------------------------------------------------------------------------------

For thsee no ID's nor gettext is used.

    { "-midiout", SET_RESOURCE, 1,
      NULL, NULL, "MIDIOutDev", NULL,
      USE_PARAM_STRING, USE_DESCRIPTION_STRING,
      IDCLS_UNUSED, IDCLS_UNUSED,
      "<name>", "Specify MIDI-Out device" },



Adding a ui_message for an architecture other than *nix, amiga or win32
-----------------------------------------------------------------------

For thsee no ID's nor gettext is used.

ui_message("this is a dialog message");
