Skip to content

Commit c18320d

Browse files
Add STYLESHEET.md
1 parent 1c62751 commit c18320d

File tree

1 file changed

+286
-0
lines changed

1 file changed

+286
-0
lines changed

STYLESHEET.md

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
# SDL3 Code Style Sheet (C to Pascal)
2+
3+
This guide helps to quickly translate often found C constructs in the
4+
SDL3 package into Pascal according to our Code style guidelines. Its
5+
goal is to have consistent code over all files in the conversion
6+
project.
7+
8+
## General Rules
9+
10+
1. Names of C defines (constants) and function parameters shall not be modified or "pascalified"
11+
Ex: `SDL_INIT_VIDEO` does not change into `SDLInitVideo`.
12+
13+
2. Names corresponding to reserved key words are kept and an underscore is added.
14+
Ex.: `type` in C function `SDL_HasEvent(Uint32 type)` changes into `type_`
15+
in Pascal function `SDL_HasEvent(type_: TSDL_EventType)`.
16+
17+
3. Use C data types like `cuint8`, `cuint16`, `cuint32`, `cint8`, `cint16`,
18+
`cint32`, `cfloat` and so on if native C data types are used in the
19+
original code. Note: For FPC you need to add the unit `ctypes` to use these C
20+
data types. For Delphi we have a temporary solution provided.
21+
22+
**Example:** Use `cuint32` (if `Uint32` is used in
23+
the original code) instead of `UInt32`, `Cardinal`, `LongWord` or `DWord`.
24+
Exception: Replace `*char` by `PAnsiChar`.
25+
26+
**Hint:** Use `TSDL_Bool` to translate `SDL_bool`. For macro functions use `Boolean`.
27+
28+
4. If an identifier or a function declaration is gone, mark them as `deprecated`.
29+
30+
5. For convenience we encourage to add single and double pointers for any SDL type.
31+
32+
## Defines
33+
34+
C:
35+
36+
```c
37+
#define SDL_HAT_CENTERED 0x00
38+
#define SDL_HAT_UP 0x01
39+
#define SDL_HAT_RIGHT 0x02
40+
#define SDL_HAT_DOWN 0x04
41+
#define SDL_HAT_LEFT 0x08
42+
#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP)
43+
#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN)
44+
#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP)
45+
#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN)
46+
```
47+
48+
Pascal:
49+
50+
```pascal
51+
const
52+
SDL_HAT_CENTERED = $00;
53+
SDL_HAT_UP = $01;
54+
SDL_HAT_RIGHT = $02;
55+
SDL_HAT_DOWN = $04;
56+
SDL_HAT_LEFT = $08;
57+
SDL_HAT_RIGHTUP = SDL_HAT_RIGHT or SDL_HAT_UP;
58+
SDL_HAT_RIGHTDOWN = SDL_HAT_RIGHT or SDL_HAT_DOWN;
59+
SDL_HAT_LEFTUP = SDL_HAT_LEFT or SDL_HAT_UP;
60+
SDL_HAT_LEFTDOWN = SDL_HAT_LEFT or SDL_HAT_DOWN;
61+
```
62+
63+
## Enums
64+
65+
C:
66+
67+
```c
68+
typedef enum
69+
{
70+
SDL_JOYSTICK_POWER_UNKNOWN = -1,
71+
SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */
72+
SDL_JOYSTICK_POWER_LOW, /* <= 20% */
73+
SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */
74+
SDL_JOYSTICK_POWER_FULL, /* <= 100% */
75+
SDL_JOYSTICK_POWER_WIRED,
76+
SDL_JOYSTICK_POWER_MAX
77+
} SDL_JoystickPowerLevel;
78+
```
79+
80+
Pascal:
81+
82+
```pascal
83+
type
84+
PPSDL_JoystickPowerLevel = ^PSDL_JoystickPowerLevel;
85+
PSDL_JoystickPowerLevel = ^TSDL_JoystickPowerLevel;
86+
TSDL_JoystickPowerLevel = type Integer;
87+
88+
const
89+
SDL_JOYSTICK_POWER_UNKNOWN = TSDL_JoystickPowerLevel(-1);
90+
SDL_JOYSTICK_POWER_EMPTY = TSDL_JoystickPowerLevel(0); {* <= 5% *}
91+
SDL_JOYSTICK_POWER_LOW = TSDL_JoystickPowerLevel(1); {* <= 20% *}
92+
SDL_JOYSTICK_POWER_MEDIUM = TSDL_JoystickPowerLevel(2); {* <= 70% *}
93+
SDL_JOYSTICK_POWER_FULL = TSDL_JoystickPowerLevel(3); {* <= 100% *}
94+
SDL_JOYSTICK_POWER_WIRED = TSDL_JoystickPowerLevel(4);
95+
SDL_JOYSTICK_POWER_MAX = TSDL_JoystickPowerLevel(5);
96+
```
97+
98+
Hint 1: C enums start at 0 if no explicit value is set.
99+
100+
Hint 2: The type should always be cint. Most C compilers have the enum elements
101+
> In C, each enumeration constant has type int and each enumeration type
102+
> is compatible with some integer type. (The integer types include all three
103+
> character types–plain, signed, and unsigned.) The choice of compatible
104+
> type is implementation-defined. The C standard grants the freedom to
105+
> use different integer types to represent different enumeration types,
106+
> but most compilers just use int to represent all enumeration types.
107+
Ref.: [https://www.embedded.com/enumerations-are-integers-except-when-theyre-not/](https://www.embedded.com/enumerations-are-integers-except-when-theyre-not/)
108+
109+
Hint 3: Do not translate C enums to Pascal enums. C enums are handled like plain
110+
integers which will make bitwise operations (e. g. in macros) possible
111+
without typecasting.
112+
113+
## Structs
114+
115+
### Defined Structs
116+
117+
C:
118+
119+
```c
120+
typedef struct SDL_version
121+
{
122+
Uint8 major; /**< major version */
123+
Uint8 minor; /**< minor version */
124+
Uint8 patch; /**< update version */
125+
} SDL_version;
126+
```
127+
128+
Pascal:
129+
130+
```pascal
131+
type
132+
PPSDL_Version = ^PSDL_Version;
133+
PSDL_Version = ^TSDL_Version;
134+
TSDL_Version = record
135+
major: cuint8 { major version }
136+
minor: cuint8 { minor version }
137+
patch: cuint8; { update version }
138+
end;
139+
```
140+
141+
### Opaque Structs
142+
143+
If you have something like ```typedef struct name name```. the concrete
144+
structure is opaque, and the programmer is expected to only ever
145+
interact with pointers to the struct.
146+
147+
C:
148+
149+
```c
150+
typedef struct SDL_Window SDL_Window;
151+
```
152+
153+
Pascal:
154+
155+
```pascal
156+
type
157+
PPSDL_Window = ^PSDL_Window;
158+
PSDL_Window = type Pointer;
159+
```
160+
161+
As shown above, for opaque structs, we avoid defining the base `TType`
162+
and define only the pointer `PType`.
163+
For the rationale behind this decision, read the discussion in
164+
[issue #63](https://github.com/PascalGameDevelopment/SDL2-for-Pascal/issues/63).
165+
166+
167+
## Unions
168+
169+
C:
170+
171+
```c
172+
typedef union {
173+
/** \brief A cutoff alpha value for binarization of the window shape's alpha channel. */
174+
Uint8 binarizationCutoff;
175+
SDL_Color colorKey;
176+
} SDL_WindowShapeParams;
177+
```
178+
179+
Pascal:
180+
181+
```pascal
182+
type
183+
PPSDL_WindowShapeParams = ^PSDL_WindowShapeParams;
184+
PSDL_WindowShapeParams = ^TSDL_WindowShapeParams;
185+
TSDL_WindowShapeParams = record
186+
case cint of
187+
{ A cutoff alpha value for binarization of the window shape's alpha channel. }
188+
0: (binarizationCutoff: cuint8);
189+
1: (colorKey: TSDL_ColorKey);
190+
end;
191+
```
192+
193+
## Functions
194+
195+
C:
196+
197+
```c
198+
extern DECLSPEC void SDLCALL SDL_LockJoysticks(void);
199+
200+
extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
201+
```
202+
203+
Pascal:
204+
205+
```pascal
206+
procedure SDL_LockJoysticks(); cdecl;
207+
external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_LockJoysticks' {$ENDIF} {$ENDIF};
208+
209+
function SDL_JoystickNameForIndex(device_index: cint): PAnsiChar; cdecl;
210+
external SDL_LibName {$IFDEF DELPHI} {$IFDEF MACOS} name '_SDL_JoystickNameForIndex' {$ENDIF} {$ENDIF};
211+
```
212+
213+
## C Macros
214+
215+
Macros are pre-processed constructs in C which have no analogue in Pascal.
216+
Usually a C macro is translated as a Pascal function and implemented in SDL2.pas.
217+
218+
C:
219+
220+
```c
221+
#define SDL_VERSION_ATLEAST(X, Y, Z) \
222+
(SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z))
223+
```
224+
225+
Pascal:
226+
227+
_sdlversion.inc (declaration)_:
228+
```pascal
229+
function SDL_VERSION_ATLEAST(X,Y,Z: cuint8): Boolean;
230+
```
231+
232+
_sdl2.pas (implementation)_:
233+
```pascal
234+
function SDL_VERSION_ATLEAST(X,Y,Z: cuint8): Boolean;
235+
begin
236+
Result := SDL_COMPILEDVERSION >= SDL_VERSIONNUM(X,Y,Z);
237+
end;
238+
```
239+
Hint: As can be seen from this example, the macro has no clearly defined
240+
argument types and return value type. The types to be used for arguments and
241+
return values depend on the context in which this macro is used. Here from the
242+
context is known that X, Y and Z stand for the major version, minor version and
243+
the patch level which are declared to be 8 bit unsigned integers. From the
244+
context it is also clear, that the macro returns true or false, hence the
245+
function should return a Boolean value. The context does not suggest to use,
246+
e. g., TSDL_Bool here, although in a different context this could be the better
247+
translation.
248+
249+
## When to use TSDL_Bool?
250+
251+
TSDL_Bool is memory compatible with C's bool (integer size, e. g. 2 or 4 bytes).
252+
Pascal's Boolean is different and typically 1 byte in size. ([FPC Ref.](https://www.freepascal.org/docs-html/current/ref/refsu4.html#x26-270003.1.1))
253+
254+
* return values and paramters of original SDL functions which are of SDL_Bool type, should be translated with TSDL_Bool
255+
* DO NOT use TSDL_Bool for macro functions which evaluate to a boolean value, use Pascal's Boolean instead (exception: the value is an argument for a SDL_Bool parameter)
256+
257+
_Example code_
258+
```pascal
259+
program SDLBoolTest;
260+
261+
uses SDL2, ctypes, SysUtils;
262+
263+
var
264+
a, b: Integer;
265+
266+
function BoolTest(a, b: Integer): TSDL_Bool;
267+
begin
268+
// works
269+
//Result := TSDL_Bool(a > b);
270+
271+
// works, too
272+
Result := (a > b);
273+
end;
274+
275+
begin
276+
writeln('Bool Test a > b');
277+
for a:= 0 to 3 do
278+
for b := 0 to 3 do
279+
begin
280+
write('a = ' + IntToStr(a) + '; b = ' + IntToStr(b) +'; Result = ');
281+
writeln(BoolTest(a, b));
282+
end;
283+
284+
readln;
285+
end.
286+
```

0 commit comments

Comments
 (0)