## Scribus Coding Standards

Initial document: Paul F. Johnson, Feb 26th 2004, Version: 0.04

This document is intended as a guide to all Scribus developers and contributors. It is aimed to be simple to use as well as to keep the source code simple to understand and maintain.

### Code Documentation

All code should be documented clearly.

Prior to any method, the following should be there

>     /*!
>      \fn functionName::functionName()
>      \author Authors Name
>      \date
>      \brief Constructor for class
>      \param None
>      \retval None
>      */

There should be something similar prior to the class definitions.

In preference, all details should be in English. This includes comments.

Unless a comment occupies a single line, `//` should be used in preference to `/* */`

### Code

#### Variable naming conventions

All variables should begin in lower case letters. If the variable has more than one part to it, then the second part should begin in a capital letter. For example `int foo` and `int fooBar`. Under no circumstances should an underscore (_) be used.

Variables should be clear in their naming. The exception to this is in a for loop. In preference, these should be in English. We are in the process of converting and altering the current ones to fit in with this.

Any temporary variables (such as those used in a `for` loop or those only used within a scope), should only be declared where they are needed and not used in a global scope. If there is a condition at the start of a method, any variables required should be declared, but nothing else. For example

>     void foo::bar(f *b)
>     {
>     	int j;
>     	string g = b->passed_in;
>     	double fg, m, c;
>     	which_string(g, &j);
>     	if (j == true)
>     		return;
>     	// rest of the code
>     }

should not have the double variables declared. It is arguable if g should be declared, but in this example, it doesn't matter.

If a variable is not required, don't create it. In the example above, there is no requirement for g to be used.

#### Tabbing convention

1. In class definitions

   With the exception of the access declarations, a single tab should be used prior to all method and variable definitions. There should be no tabs prior to access declarations. There is a tab prior to `Q_Object`.

2. In the main code

   There should be a tab at the start of every line. With any conditional line, there should be an opening brace by itself. On the next line down, there should be another tab prior to any code. The close brace should be underneath the open brace.

#### Conditionals

Always make a conditional logical. This may sound silly, but look at the following example

>     int foobar(bool m)
>     {
>     	if (m == true)
>     	{
>     		somethingA(1);
>     		somethingB(1);
>     		somethingB(1);
>     	}
>     	else
>     	{
>     		somethingA(0);
>     		somethingB(0);
>     		somethingC(0);
>     	}
>     }

This can be re-written to make things clearer

>     int foobar(bool m)
>     {
>        int c = m == true ? 1 : 0;
>        somethingA(c);
>        somethingB(c);
>        somethingC(c);
>     }

A lot simpler to see and will usually optimise far better.

Ternary conditionals (?) should be used in preference to `if` / `else`. These are usually far quicker to process the code once compiled.

Depending on what is being performed, switch statements should be avoided. There is usually a simpler way to avoid them. For example

>     int b;
>     string s;
>     switch (f)
>     {
>     	case 1 :
>     		b = 4;
>     		s = "four";
>     		break;
>     	case 2 :
>     		b = 8;
>     		s = "eight";
>     		break;
>     	case 3 :
>     		b = 12;
>     		s = "twelve";
>     }

can be re-written as

>     int b = f * 4;
>     char *number[] = {"four", "eight", "twelve"};
>     size_t no = sizeof(number) / sizeof(*number);
>     s = number(f);

The switch has gone and the code generated runs far faster and as the conditions don't need to be created, will optimise far better. Note: when using the `QObject::tr()` function, this method of using char* may not always work properly. An alternative is to use `QString number[] = {"four", "eight", "twelve"};` etc.

Obviously for more complex switch conditions, the above can't be used.

#### Conditionals formatting

Formatting should look like this:

>     if (fred == 5)
>     {
>     	// something
>     	// something
>     }

Switch formatting should look like this:

>     switch (f)
>     {
>     	case 0:
>     		if (fred == 1)
>     		{
>     			// something
>     			// more
>     			// ok
>     		}
>     		else
>     		{
>     			if (jimmy == 0)
>     			{
>     				// hi
>     				// code
>     			}
>     			// something here
>     		}
>     		break;
>     }

Simple to read and simple to see where the conditional ends.

Under NO circumstances should you have a line such as:

>     if (foo == bar) { somethingA(0); }

This should be written as:

>     if (foo == bar)
>     	somethingA(0);

If braces are not required, don't use them. For example, braces wouldn't be needed here

>     for (int j = 0; j < 10; ++j)
>     	cout << j << "\n"?;

#### Pre or post increments

In for loops, preincrements should be used (++a rather than a++). Under ARM processors and x64 processors (not sure about ia64) ++a requires half the number of clock cycles than the post processor style. In some circumstances, ++a is far more efficient under ia32. It is even more efficient when used with iterators. Post increments should be used in the following sort of code:

>     if (b == true)
>     {
>     	m->wibble(c);
>     	m->wobble(c++);
>     }

#### Spacings

There should be a space after:

- All commas and semi-colons (in a for condition)
- Between any conditional (`if (a == true)` - there is a space either side of the `==` conditional)

- Prior to an open bracket or after a close bracket:

  - A space should not be used immediately inside or at the end of a bracket
  - Do not use spaces at the beginning of lines. You must use a tab. A tab will always be a finite number of spaces, the number of spaces can vary when hand inputted.

#### Use of templates

Templates for both types and classes are fine to be used. The project recommends using g++ 3.x which fully support templates and template classes. Please remember the overhead involved in using templates!

When using templates, please remember the following:

- The final binary will be larger
- To use them correctly. It is very easy to say "I can just whizz that over to a template" when actually, it would be far better to construct (say) a generic template class which inherits the base Qt classes in question.
- In some places, a template will not be as efficient as a standalone call.

#### Optimisation

Unless you really know what you're doing and more over, what the code is doing, do not attempt to do any code optimisation. In a lot of respects, optimisation is a "black art".

Code such as `a = b = c = 0;` is more efficient (through the compiler) than `a=0; b=0; c=0;`

Careful thought about how the code works is usually far more benificial than attempting any of the "tricks" currently employed.

Any large scale changes should be approved of first. Sometimes a small change can have large side effects.

Multiple separate lines containing calls to Qt methods are far less efficient than multiple calls contained in a for loop.

#### Memory checking

All calls to `new` should be trapped. This is not currently implemented in the 1.1.x releases, but will be implemented in the 1.2. The preferred method would be:

>     #include

>     try
>     {
>       m = new int[2048];
>     }

>     catch(bad_exception)
>     {
>       cout << "memory allocation to m failed - " << endl;
>       exit(EXIT_FAILURE);
>     }

As there are many calls in Scribus to new, these will have a wrapper around.

For users of Qt who compile their own, they will need to include in the `./configure` script that they want to throw C++ exceptions. Failure to do so will result in the catches not catching and possibly Scribus failing to run.

Currently (for v3.2), KDE recommend Qt is compiled without exceptions. This is a bad idea as it means trapping bad memory allocations cannot be caught using the prefered method.

#### Submitting of patches

Code patches should be sent to Franz and Paul. Documentation patches should be sent to Peter and Craig. This is subject to change. Scripting matters should be addressed to Petr.

Patches should be in plain text. diff -u old_file.cpp new_file.cpp >difference.diff is the best way of sending them. Please do not send patches to the main list.

Please ensure that when you have changed something you put a comment immediately before the change. Ensure you put a date and who made the change and what the change is for. Make sure that the comments include the original line of code. Over time, these will be weeded out, but it useful to see what has been altered.

Send a single diff for each file altered. It makes committing the changes far more simple for us!

#### Writing plugin scripts.

Please use the current functions and refer to the Plugin howto for further information.

All code has to be encompassed within an `extern "C" { ... };` to enable the plugin to work. Ensure that all the code is documented and follows the coding guidelines set out above.