summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornasr <nsrddyn@gmail.com>2026-03-13 22:31:21 +0100
committernasr <nsrddyn@gmail.com>2026-03-13 22:31:21 +0100
commit444bfa2f41143aff7490e4fa21565947565b7d30 (patch)
tree696b06d40140c85805d171597e37deb8290ead73
parent3913d1778318cd0c6bfb871148d38abb33ec7fd3 (diff)
cleanup: generalisation
-rw-r--r--.clang-format104
-rw-r--r--.clangd57
-rw-r--r--base/base.c69
-rw-r--r--base/base.h85
-rw-r--r--base/base_arena.c86
-rw-r--r--base/base_arena.h49
-rwxr-xr-xbuild.sh42
-rwxr-xr-xbuild/appbin0 -> 73432 bytes
-rwxr-xr-xbuild/libcore.so (renamed from main)bin85960 -> 69888 bytes
-rw-r--r--library/arena.c81
-rw-r--r--library/arena.h69
-rw-r--r--library/base.h42
-rw-r--r--library/clang-format104
-rw-r--r--library/clangd59
-rw-r--r--main.c257
-rwxr-xr-xrun.sh8
-rwxr-xr-xsource/base/base.h77
-rwxr-xr-xsource/base/base_arena.c142
-rwxr-xr-xsource/base/base_arena.h41
-rw-r--r--source/base/base_hash.c18
-rwxr-xr-xsource/base/base_include.h30
-rw-r--r--source/base/base_mem.c17
-rw-r--r--source/base/base_mem.h8
-rwxr-xr-xsource/base/base_parse.c98
-rwxr-xr-xsource/base/base_parse.h28
-rwxr-xr-xsource/base/base_stack.c187
-rwxr-xr-xsource/base/base_stack.h20
-rw-r--r--source/base/base_string.c73
-rw-r--r--source/base/base_string.h17
-rw-r--r--source/base/base_test.c14
-rw-r--r--source/base/base_test.h61
-rw-r--r--source/base/bash_hash.h15
-rw-r--r--source/core/core.c126
-rw-r--r--source/core/core.h5
-rw-r--r--source/platform/platform.c12
-rw-r--r--source/platform/platform.h56
-rw-r--r--source/platform/platform_include.h7
-rw-r--r--xlib-tutorial/2nd-program-anatomy.html282
-rw-r--r--xlib-tutorial/Xlib.pdfbin357941 -> 0 bytes
-rw-r--r--xlib-tutorial/index.html116
-rw-r--r--xlib-tutorial/prog-1.cc29
-rw-r--r--xlib-tutorial/prog-2.cc74
-rw-r--r--xlib-tutorial/server.html89
43 files changed, 1080 insertions, 1674 deletions
diff --git a/.clang-format b/.clang-format
deleted file mode 100644
index 0929f7f..0000000
--- a/.clang-format
+++ /dev/null
@@ -1,104 +0,0 @@
1BasedOnStyle: LLVM
2Language: Cpp
3
4# -------------------------------------------------------------------
5# Indentation & layout
6# -------------------------------------------------------------------
7IndentWidth: 2
8TabWidth: 2
9UseTab: Never
10ContinuationIndentWidth: 2
11
12IndentCaseLabels: true
13IndentGotoLabels: true
14IndentPPDirectives: None
15IndentExternBlock: NoIndent
16
17# -------------------------------------------------------------------
18# Line breaking
19# -------------------------------------------------------------------
20ColumnLimit: 0
21
22AllowAllParametersOfDeclarationOnNextLine: false
23AllowAllArgumentsOnNextLine: false
24
25AllowShortFunctionsOnASingleLine: None
26AllowShortIfStatementsOnASingleLine: Never
27AllowShortLoopsOnASingleLine: false
28AllowShortBlocksOnASingleLine: Never
29AllowShortCaseLabelsOnASingleLine: false
30
31AlwaysBreakAfterReturnType: All
32AlwaysBreakTemplateDeclarations: No # harmless for C
33
34BreakBeforeBinaryOperators: None
35
36# -------------------------------------------------------------------
37# Braces (Allman style)
38# -------------------------------------------------------------------
39BreakBeforeBraces: Allman
40
41BraceWrapping:
42 AfterCaseLabel: true
43 BeforeElse: true
44 BeforeCatch: true
45 SplitEmptyFunction: true
46 SplitEmptyRecord: true
47 SplitEmptyNamespace: true
48
49# NOTE:
50# AfterControlStatement / AfterFunction / AfterStruct / AfterEnum / AfterUnion
51# are IMPLIED by Allman and must NOT be redundantly specified.
52
53# -------------------------------------------------------------------
54# Spacing
55# -------------------------------------------------------------------
56SpaceBeforeParens: ControlStatements
57SpaceBeforeAssignmentOperators: true
58SpaceBeforeRangeBasedForLoopColon: true # ignored in C, harmless
59
60SpacesInParentheses: false
61SpacesInSquareBrackets: false
62SpacesInAngles: false
63SpaceInEmptyParentheses: false
64SpacesBeforeTrailingComments: 1
65
66PointerAlignment: Right
67DerivePointerAlignment: false
68
69# -------------------------------------------------------------------
70# Alignment (explicitly disabled)
71# -------------------------------------------------------------------
72AlignAfterOpenBracket: DontAlign
73AlignOperands: false
74AlignTrailingComments: false
75AlignConsecutiveAssignments: false
76AlignConsecutiveDeclarations: false
77AlignEscapedNewlines: DontAlign
78
79# -------------------------------------------------------------------
80# Comments
81# -------------------------------------------------------------------
82ReflowComments: Never
83CommentPragmas: '^ dont touch:'
84KeepEmptyLinesAtTheStartOfBlocks: false
85MaxEmptyLinesToKeep: 1
86
87# -------------------------------------------------------------------
88# Includes
89# -------------------------------------------------------------------
90SortIncludes: Never
91IncludeBlocks: Preserve
92
93# -------------------------------------------------------------------
94# Macros & preprocessor
95# -------------------------------------------------------------------
96MacroBlockBegin: ''
97MacroBlockEnd: ''
98SpaceAfterCStyleCast: false
99
100# -------------------------------------------------------------------
101# C-specific
102# -------------------------------------------------------------------
103Cpp11BracedListStyle: false
104DisableFormat: false
diff --git a/.clangd b/.clangd
deleted file mode 100644
index 759ad19..0000000
--- a/.clangd
+++ /dev/null
@@ -1,57 +0,0 @@
1CompileFlags:
2 # Add:
3 # - -std=c99
4 # - -xc
5 #
6 # - -Iinclude
7 # - -Wall
8 # - -Wextra
9 # - -Wpedantic
10 # - -Wshadow
11 # - -Wconversion
12 # - -Wsign-conversion
13 # - -Wmissing-declarations
14 # - -Wundef
15 # - -Wpointer-arith
16 # - -Wcast-align
17 # - -Wcast-qual
18 # - -Wwrite-strings
19 # - -Wswitch-enum
20 # - -Wformat=2
21 # - -Wstrict-aliasing=2
22 # - -Werror=implicit-function-declaration
23 # - -Werror=implicit-int
24 # - -Werror=incompatible-pointer-types
25 # - -Werror=return-type
26 # - -Wformat-security
27 # - -Wnull-dereference
28 # - -Wmisleading-indentation
29 #
30 # - -Wuninitialized
31 # - -Werror
32 # - -Wdouble-promotion
33 # - -Wstrict-overflow=2
34 #
35 # - -D_POSIX_C_SOURCE=200809L
36 # - "-I/include"
37
38 Remove:
39 - -std=*
40 - -O*
41 - -march=*
42 - -mtune=*
43
44
45Hover:
46 ShowAKA: true
47
48InlayHints:
49 Enabled: true
50 ParameterNames: true
51 DeducedTypes: true
52
53Completion:
54 AllScopes: true
55
56Index:
57 Background: Build
diff --git a/base/base.c b/base/base.c
deleted file mode 100644
index ba8ba32..0000000
--- a/base/base.c
+++ /dev/null
@@ -1,69 +0,0 @@
1#include "base/base.h"
2#include "stddef.h"
3
4/**
5 * Helper function to parse strings to int using ascii codes
6 * */
7local_internal u64
8parse_u64(char *buf, size_t len)
9{
10 u64 value = 0;
11
12 for (
13 size_t buffer_idx = 0;
14 buffer_idx < len;
15 ++buffer_idx)
16 {
17 char c = buf[buffer_idx];
18 if (c < '0' || c > '9')
19 {
20 break;
21 }
22 value = value * 10 + (c - '0');
23 }
24
25 return value;
26}
27
28/*
29 * is_numeric - Check if a string contains only digits
30 * @s: String to check
31 *
32 * Return: 1 if string contains only numeric characters, 0 otherwise
33 */
34local_internal b8
35is_numeric(char *s)
36{
37 for (; *s; ++s)
38 {
39 if (*s < '0' || *s > '9')
40 {
41 return 0;
42 }
43 }
44 return 1;
45}
46
47local_internal b8
48compare_string(const char *c1, const char *c2)
49{
50 if (sizeof(c1) != sizeof(c2))
51 {
52 return -1;
53 }
54
55 for (
56 u64 word_idx = 0;
57 word_idx <= sizeof(*c1);
58 ++word_idx)
59 {
60 if (*c1 != *c2)
61 {
62 return -1;
63 }
64 ++c1;
65 ++c2;
66 }
67
68 return 0;
69}
diff --git a/base/base.h b/base/base.h
deleted file mode 100644
index 8ce6cba..0000000
--- a/base/base.h
+++ /dev/null
@@ -1,85 +0,0 @@
1#ifndef BASE_H
2#define BASE_H
3
4#include <stdint.h>
5#include <stddef.h>
6
7/* assert an expression and output the file and the line */
8
9#define RED "\x1b[31m"
10#define GREEN "\x1b[32m"
11#define RESET "\x1b[0m"
12
13#define test_assert(expr) \
14 do \
15 { \
16 if (!(expr)) \
17 { \
18 fprintf(stderr, RED " [FAILED] %s:%d: expr:%s test:%s\n" RESET, __FILE__, __LINE__, #expr, __func__); \
19 abort(); \
20 } \
21 else\
22 { \
23 fprintf(stdout, GREEN "[PASSED] %s\n" RESET, __func__); \
24 }\
25 } while (0)
26
27#define global_variable static
28#define local_persist static
29#define local_internal static
30
31#define ERR_OK 0
32#define ERR_IO 1
33#define ERR_PARSE 2
34#define ERR_PERM 3
35#define ERR_INVALID 4
36
37#define KiB(n) (((u64)(n)) << 10)
38#define MiB(n) (((u64)(n)) << 20)
39#define GiB(n) (((u64)(n)) << 30)
40
41#define BUFFER_SIZE_SMALL 128
42#define BUFFER_SIZE_DEFAULT 256
43#define BUFFER_SIZE_LARGE 512
44#define PATH_MAX_LEN 4096
45
46#define DEPRECATED __attribute__((__deprecated__))
47
48typedef uint64_t u64;
49typedef uint32_t u32;
50typedef uint16_t u16;
51typedef uint8_t u8;
52
53typedef int8_t i8;
54typedef int16_t i16;
55typedef int32_t i32;
56typedef int64_t i64;
57
58typedef float f32;
59typedef double f64;
60
61typedef i32 b32;
62typedef i16 b16;
63typedef u8 b8;
64
65typedef uintptr_t umm;
66typedef intptr_t smm;
67
68#define TRUE 1
69#define FALSE 0
70
71local_internal u64
72parse_u64(char *buf, size_t len);
73
74local_internal b8
75is_numeric(char *s);
76
77local_internal b8
78compare_string(const char *c1, const char *c2);
79
80/*
81 * TODO(nasr): macro for verbose assertions
82 *
83 * */
84
85#endif
diff --git a/base/base_arena.c b/base/base_arena.c
deleted file mode 100644
index 16997b2..0000000
--- a/base/base_arena.c
+++ /dev/null
@@ -1,86 +0,0 @@
1/**
2 * TODO(nasr): remove stdlib
3 * */
4#include <assert.h>
5#include <stdint.h>
6#include <string.h>
7#include <sys/mman.h>
8#include <sys/stat.h>
9#include <dirent.h>
10#include <fcntl.h>
11#include <unistd.h>
12
13#include "base_arena.h"
14
15/* TODO(nasr): reserve pages support */
16/* TODO(nasr): check if an arena has been used before */
17
18local_internal mem_arena *
19arena_create(u64 capacity)
20{
21 mem_arena *arena = (mem_arena *)mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC,
22 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
23 if (arena == MAP_FAILED)
24 {
25 return NULL;
26 }
27
28 arena->capacity = capacity;
29 arena->pos = ARENA_BASE_POS;
30
31 return arena;
32}
33
34/*
35 * make it a void pointer to allow implicit conversion
36 * */
37local_internal void
38arena_destroy(mem_arena *arena)
39{
40 munmap(arena, arena->capacity);
41}
42
43local_internal void *
44arena_push(mem_arena *arena, u64 size, b32 non_zero)
45{
46 u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN);
47 u64 new_pos = pos_aligned + size;
48
49 if (new_pos > arena->capacity)
50 {
51 assert(0);
52 return NULL;
53 }
54
55 arena->pos = new_pos;
56 /*
57 * cast to u8 to be able to do pointer arithemtic
58 * */
59 u8 *out = (u8 *)arena + pos_aligned;
60
61 if (!non_zero)
62 {
63 memset(out, 0, size);
64 }
65 return out;
66}
67
68local_internal void
69arena_pop(mem_arena *arena, u64 size)
70{
71 size = MIN(size, arena->pos - ARENA_BASE_POS);
72 arena->pos -= size;
73}
74
75local_internal void
76arena_pop_to(mem_arena *arena, u64 pos)
77{
78 u64 size = pos < arena->pos ? arena->pos - pos : 0;
79 arena_pop(arena, size);
80}
81
82local_internal void
83arena_clear(mem_arena *arena)
84{
85 arena_pop_to(arena, ARENA_BASE_POS);
86}
diff --git a/base/base_arena.h b/base/base_arena.h
deleted file mode 100644
index 19c4f3d..0000000
--- a/base/base_arena.h
+++ /dev/null
@@ -1,49 +0,0 @@
1#ifndef ARENA_H
2#define ARENA_H
3
4#include "base.h"
5
6/**
7 * Arena Helper macro's
8 * */
9
10#define MIN(a, b) (((a) < (b)) ? (a) : (b))
11#define MAX(a, b) (((a) > (b)) ? (a) : (b))
12#define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1)))
13
14#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0)
15#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1)
16#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0)
17#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1)
18
19#define ARENA_BASE_POS (sizeof(mem_arena))
20#define ARENA_ALIGN (sizeof(void *))
21
22typedef struct mem_arena mem_arena;
23
24struct mem_arena
25{
26 u64 capacity;
27 u64 pos;
28};
29
30local_internal mem_arena *
31arena_create(u64 capacity);
32
33local_internal void
34arena_destroy(mem_arena *arena);
35
36local_internal void *
37arena_push(mem_arena *arena, u64 size, b32 non_zero);
38
39local_internal void
40arena_pop(mem_arena *arena, u64 size);
41
42local_internal void
43arena_pop_to(mem_arena *arena, u64 pos);
44
45local_internal void
46arena_clear(mem_arena *arena);
47
48
49#endif
diff --git a/build.sh b/build.sh
index 80f3d5a..e602edb 100755
--- a/build.sh
+++ b/build.sh
@@ -1,31 +1,29 @@
1#!/bin/sh 1#!/bin/sh
2set -eu 2set -eu
3 3
4# Toolchain 4script_dir="$(dirname "$(readlink -f "$0")")"
5CC=clang 5cd "$script_dir"
6 6
7# Files 7build_dir="build"
8SRC=main.c 8mkdir -p "$build_dir"
9OUT=main
10 9
11# Include paths 10compile()
12INCLUDES="-I." 11{
12 source="$1"
13 out="$2"
14 flags="${3:-}"
13 15
14# Compiler flags 16 common_flags="-I. -Wall -Wextra -Wno-unused-function -Wno-unused-variable"
15CFLAGS=" 17 linker_flags="-lX11 -lm"
16-g
17-O0
18"
19 18
20# Linker flags 19 flags="$common_flags $flags $linker_flags"
21LDFLAGS="
22-lX11
23-I.
24-lm
25"
26 20
27echo "==> Building $OUT" 21 gcc $flags "$(readlink -f "$source")" -o "$build_dir"/"$out"
28$CC $CFLAGS $INCLUDES "$SRC" -o "$OUT" $LDFLAGS 22}
23
24# Build core shared lib
25compile "source/core/core.h" "libcore.so" "-fPIC -shared -DCORE_UNITY"
26
27# Build app
28compile "source/core/core.c" "app" "-L$build_dir -lcore"
29 29
30echo "==> Running $OUT"
31./"$OUT"
diff --git a/build/app b/build/app
new file mode 100755
index 0000000..5220177
--- /dev/null
+++ b/build/app
Binary files differ
diff --git a/main b/build/libcore.so
index 28736dd..1026809 100755
--- a/main
+++ b/build/libcore.so
Binary files differ
diff --git a/library/arena.c b/library/arena.c
deleted file mode 100644
index 39711d5..0000000
--- a/library/arena.c
+++ /dev/null
@@ -1,81 +0,0 @@
1#include <assert.h>
2#include <dirent.h>
3#include <fcntl.h>
4#include <stdint.h>
5#include <string.h>
6#include <sys/mman.h>
7#include <sys/stat.h>
8#include <unistd.h>
9
10#include "arena.h"
11
12mem_arena *
13arena_create(u64 capacity)
14{
15 mem_arena *arena = mmap(0, capacity, PROT_READ | PROT_WRITE | PROT_EXEC,
16 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
17 if (arena == MAP_FAILED)
18 {
19 assert(0);
20 }
21
22 arena->capacity = capacity;
23 arena->pos = ARENA_BASE_POS;
24
25 return arena;
26}
27
28// make it a void pointer to allow implicit conversion
29void
30arena_destroy(mem_arena *arena)
31{
32 munmap(arena, arena->capacity);
33}
34
35void *
36arena_push(mem_arena *arena, u64 size, b32 non_zero)
37{
38 u64 pos_aligned = ALIGN_UP_POW2(arena->pos, ARENA_ALIGN);
39 u64 new_pos = pos_aligned + size;
40
41 if (new_pos > arena->capacity)
42 {
43 assert(0);
44 return NULL;
45 }
46
47 arena->pos = new_pos;
48 // cast to u8 to be able to do pointer arithemtic
49 u8 *out = (u8 *)arena + pos_aligned;
50
51 if (!non_zero)
52 {
53 memset(out, 0, size);
54 }
55 return out;
56}
57void
58arena_pop(mem_arena *arena, u64 size)
59{
60 size = MIN(size, arena->pos - ARENA_BASE_POS);
61 arena->pos -= size;
62}
63
64void
65arena_pop_to(mem_arena *arena, u64 pos)
66{
67 u64 size = pos < arena->pos ? arena->pos - pos : 0;
68 arena_pop(arena, size);
69}
70
71void
72arena_clear(mem_arena *arena)
73{
74 arena_pop_to(arena, ARENA_BASE_POS);
75}
76
77#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0)
78#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1)
79#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0)
80#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1)
81
diff --git a/library/arena.h b/library/arena.h
deleted file mode 100644
index 330023e..0000000
--- a/library/arena.h
+++ /dev/null
@@ -1,69 +0,0 @@
1#ifndef ARENA_H
2#define ARENA_H
3
4#include "base.h"
5
6/**
7 * Arena Helper macro's
8 * */
9
10#define MIN(a, b) (((a) < (b)) ? (a) : (b))
11#define MAX(a, b) (((a) > (b)) ? (a) : (b))
12#define ALIGN_UP_POW2(n, p) (((u64)(n) + ((u64)(p) - 1)) & (~((u64)(p) - 1)))
13
14
15
16/*
17 * Represents a disk partition with major/minor device numbers and block count.
18 */
19
20/**
21 * replacing malloc/free with arena allocaters
22 *
23 * */
24
25#define ARENA_BASE_POS (sizeof(mem_arena))
26// void * for the size of a pointer on the machine, 64/32bit comp
27#define ARENA_ALIGN (sizeof(void *))
28
29
30static inline u64 KiB(u64 n) { return n << 10; }
31static inline u64 MiB(u64 n) { return n << 20; }
32static inline u64 GiB(u64 n) { return n << 30; }
33
34typedef struct mem_arena mem_arena;
35
36
37struct mem_arena
38{
39 u64 capacity;
40 u64 pos;
41} ;
42
43// arena prototypes
44mem_arena *
45arena_create(u64 capacity);
46// make it a void pointer to allow implicit conversion
47void
48arena_destroy(mem_arena *arena);
49
50void *
51arena_push(mem_arena *arena, u64 size, b32 non_zero);
52
53void
54arena_pop(mem_arena *arena, u64 size);
55
56void
57arena_pop_to(mem_arena *arena, u64 pos);
58
59void
60arena_clear(mem_arena *arena);
61
62
63#define PUSH_STRUCT(arena, T) (T *)arena_push((arena), sizeof(T), 0)
64#define PUSH_STRUCT_NZ(arena, T) (T *)arena_push((arena), sizeof(T), 1)
65#define PUSH_ARRAY(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 0)
66#define PUSH_ARRAY_NZ(arena, T, n) (T *)arena_push((arena), sizeof(T) * (n), 1)
67
68
69#endif
diff --git a/library/base.h b/library/base.h
deleted file mode 100644
index 74b6303..0000000
--- a/library/base.h
+++ /dev/null
@@ -1,42 +0,0 @@
1#ifndef BASE_H
2#define BASE_H
3
4#include <stddef.h>
5#include <stdint.h>
6
7#define OK 0
8#define ERR_IO 1
9#define ERR_PARSE 2
10#define ERR_PERM 3
11#define ERR_INVALID 4
12
13enum {
14 BUFFER_SIZE_SMALL = 128,
15 BUFFER_SIZE_DEFAULT = 256,
16 BUFFER_SIZE_LARGE = 512,
17 PATH_MAX_LEN = 4096
18};
19
20typedef uint64_t u64;
21typedef uint32_t u32;
22typedef uint16_t u16;
23typedef uint8_t u8;
24
25typedef int8_t i8;
26typedef int16_t i16;
27typedef int32_t i32;
28typedef int64_t i64;
29
30typedef float f32;
31typedef double f64;
32
33typedef i32 b32;
34typedef i16 b16;
35typedef u8 b8;
36
37#define TRUE 1
38#define FALSE 0
39
40
41
42#endif
diff --git a/library/clang-format b/library/clang-format
deleted file mode 100644
index 3c61d5e..0000000
--- a/library/clang-format
+++ /dev/null
@@ -1,104 +0,0 @@
1BasedOnStyle: LLVM
2Language: C
3
4# -------------------------------------------------------------------
5# Indentation & layout
6# -------------------------------------------------------------------
7IndentWidth: 2
8TabWidth: 2
9UseTab: Never
10ContinuationIndentWidth: 2
11
12IndentCaseLabels: true
13IndentGotoLabels: true
14IndentPPDirectives: None
15IndentExternBlock: NoIndent
16
17# -------------------------------------------------------------------
18# Line breaking
19# -------------------------------------------------------------------
20ColumnLimit: 0
21
22AllowAllParametersOfDeclarationOnNextLine: false
23AllowAllArgumentsOnNextLine: false
24
25AllowShortFunctionsOnASingleLine: false
26AllowShortIfStatementsOnASingleLine: Never
27AllowShortLoopsOnASingleLine: false
28AllowShortBlocksOnASingleLine: Never
29AllowShortCaseLabelsOnASingleLine: false
30
31AlwaysBreakAfterReturnType: All
32AlwaysBreakTemplateDeclarations: No # harmless for C
33
34BreakBeforeBinaryOperators: None
35
36# -------------------------------------------------------------------
37# Braces (Allman style)
38# -------------------------------------------------------------------
39BreakBeforeBraces: Allman
40
41BraceWrapping:
42 AfterCaseLabel: true
43 BeforeElse: true
44 BeforeCatch: true
45 SplitEmptyFunction: true
46 SplitEmptyRecord: true
47 SplitEmptyNamespace: true
48
49# NOTE:
50# AfterControlStatement / AfterFunction / AfterStruct / AfterEnum / AfterUnion
51# are IMPLIED by Allman and must NOT be redundantly specified.
52
53# -------------------------------------------------------------------
54# Spacing
55# -------------------------------------------------------------------
56SpaceBeforeParens: ControlStatements
57SpaceBeforeAssignmentOperators: true
58SpaceBeforeRangeBasedForLoopColon: true # ignored in C, harmless
59
60SpacesInParentheses: false
61SpacesInSquareBrackets: false
62SpacesInAngles: false
63SpaceInEmptyParentheses: false
64SpacesBeforeTrailingComments: 1
65
66PointerAlignment: Right
67DerivePointerAlignment: false
68
69# -------------------------------------------------------------------
70# Alignment (explicitly disabled)
71# -------------------------------------------------------------------
72AlignAfterOpenBracket: DontAlign
73AlignOperands: false
74AlignTrailingComments: false
75AlignConsecutiveAssignments: false
76AlignConsecutiveDeclarations: false
77AlignEscapedNewlines: DontAlign
78
79# -------------------------------------------------------------------
80# Comments
81# -------------------------------------------------------------------
82ReflowComments: false
83CommentPragmas: '^ dont touch:'
84KeepEmptyLinesAtTheStartOfBlocks: false
85MaxEmptyLinesToKeep: 1
86
87# -------------------------------------------------------------------
88# Includes
89# -------------------------------------------------------------------
90SortIncludes: Never
91IncludeBlocks: Preserve
92
93# -------------------------------------------------------------------
94# Macros & preprocessor
95# -------------------------------------------------------------------
96MacroBlockBegin: ''
97MacroBlockEnd: ''
98SpaceAfterCStyleCast: false
99
100# -------------------------------------------------------------------
101# C-specific
102# -------------------------------------------------------------------
103Cpp11BracedListStyle: false
104DisableFormat: false
diff --git a/library/clangd b/library/clangd
deleted file mode 100644
index 624678a..0000000
--- a/library/clangd
+++ /dev/null
@@ -1,59 +0,0 @@
1CompileFlags:
2 Add:
3 - -std=c99
4 - -xc
5
6 - -Iinclude
7
8 - -Wall
9 - -Wextra
10 - -Wpedantic
11 - -Wshadow
12 - -Wconversion
13 - -Wsign-conversion
14 - -Wmissing-declarations
15 - -Wundef
16 - -Wpointer-arith
17 - -Wcast-align
18 - -Wcast-qual
19 - -Wwrite-strings
20 - -Wswitch-enum
21 - -Wformat=2
22 - -Wstrict-aliasing=2
23 - -Werror=implicit-function-declaration
24 - -Werror=implicit-int
25 - -Werror=incompatible-pointer-types
26 - -Werror=return-type
27 - -Wformat-security
28 - -Wnull-dereference
29 - -Wmisleading-indentation
30
31 - -Wunused
32 - -Wuninitialized
33 - -Werror
34 - -Wdouble-promotion
35 - -Wstrict-overflow=2
36
37 - -D_POSIX_C_SOURCE=200809L
38 - "-I/include"
39
40 Remove:
41 - -std=*
42 - -O*
43 - -march=*
44 - -mtune=*
45
46
47Hover:
48 ShowAKA: true
49
50InlayHints:
51 Enabled: true
52 ParameterNames: true
53 DeducedTypes: true
54
55Completion:
56 AllScopes: true
57
58Index:
59 Background: Build
diff --git a/main.c b/main.c
deleted file mode 100644
index 4c43245..0000000
--- a/main.c
+++ /dev/null
@@ -1,257 +0,0 @@
1#include <X11/X.h>
2#include <X11/Xlib.h>
3#include <stdint.h>
4#include <string.h>
5#include <time.h>
6#include <unistd.h>
7#include <stdio.h>
8
9#include "base/base.h"
10#include "base/base_arena.h"
11
12#include "base/base.c"
13#include "base/base_arena.c"
14
15
16#define NIL 0
17
18typedef struct
19{
20i32 x;
21i32 y;
22u32 height;
23u32 width;
24u32 border_width;
25i32 window_depth;
26u32 window_class;
27u64 value_mask;
28
29} WindowProperties;
30
31typedef struct
32{
33i32 x;
34i32 y;
35i32 z;
36
37} vertex;
38
39void
40sleep_ms(long ms)
41{
42struct timespec ts;
43ts.tv_sec = ms / 1000;
44ts.tv_nsec = (ms % 1000) * 1000000L;
45
46while (nanosleep(&ts, &ts))
47{
48NULL;
49}
50}
51
52void
53move_down(double *y)
54{
55++*y;
56}
57
58void
59move_up(double *y)
60{
61--*y;
62}
63
64void
65move_left(double *x)
66{
67--*x;
68}
69
70void
71move_right(double *x)
72{
73++*x;
74}
75
76
77
78typedef struct
79{
80void (*move)(double *a);
81} movement;
82
83void
84handle_destroy(Display *display, GC *gc)
85{
86XFreeGC(display, *gc);
87XCloseDisplay(display);
88}
89
90typedef struct
91{
92i32 x;
93i32 y;
94
95} display_pos;
96
97typedef struct
98{
99i32 x;
100i32 y;
101i32 z;
102
103} pos;
104
105
106int
107main()
108{
109Display *MainDisplay = XOpenDisplay(0);
110mem_arena *arena = arena_create(MiB(8));
111
112Window root = XDefaultRootWindow(MainDisplay);
113int screen = DefaultScreen(MainDisplay);
114
115Visual *v = DefaultVisual(MainDisplay, screen);
116
117XSetWindowAttributes wa = {
118.background_pixmap = None,
119.background_pixel = BlackPixel(MainDisplay, DefaultScreen(MainDisplay)),
120.border_pixmap = CopyFromParent,
121.border_pixel = 0,
122.bit_gravity = ForgetGravity,
123.win_gravity = NorthWestGravity,
124.backing_store = NotUseful,
125.backing_planes = 1,
126.backing_pixel = 0,
127.save_under = False,
128.event_mask = {},
129.do_not_propagate_mask = {},
130.override_redirect = False,
131.colormap = CopyFromParent,
132.cursor = None
133};
134
135i32 dp_heigth = DisplayHeight(MainDisplay, screen);
136i32 dp_width = DisplayWidth(MainDisplay, screen);
137
138WindowProperties p = {
139
140.x = dp_width / 2,
141.y = dp_heigth / 2,
142.height = (u32)800,
143.width = (u32)1200,
144.border_width = 0,
145.window_depth = CopyFromParent,
146.window_class = CopyFromParent,
147.value_mask = CWBackPixel,
148
149};
150
151
152Window window =
153XCreateWindow(
154MainDisplay,
155root,
156p.x,
157p.y,
158p.width,
159p.height,
160p.border_width,
161p.window_depth,
162p.window_class,
163v,
164p.value_mask,
165&wa);
166
167Pixmap pixmap = XCreatePixmap(MainDisplay, window, dp_width, dp_heigth, 1);
168
169XSetWindowBorder(MainDisplay, window, 60);
170XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask);
171XMapWindow(MainDisplay, window);
172
173
174double x = p.width / 2;
175double y = p.height / 2;
176
177u32 rect_width = 50;
178u32 rect_height = 50;
179
180u64 color = 0x0000ff00;
181
182GC gc = XCreateGC(MainDisplay, window, 0, NIL);
183XSetForeground(MainDisplay, gc, color);
184
185
186double *pX = &x;
187double *pY = &y;
188
189movement m = {
190.move = move_down
191};
192
193XEvent event;
194XNextEvent(MainDisplay, &event);
195
196for (;;)
197{
198switch (event.type)
199case KeyPress:
200case KeyRelease:
201{
202
203
204}
205default:
206{
207if (*pX + rect_width >= p.width)
208{
209m.move = move_left;
210}
211else if (*pX <= 0)
212{
213m.move = move_right;
214}
215
216char words[] = "working";
217
218XTextItem ti = {
219.chars = words,
220.nchars = (int)strlen(words),
221.delta = 0,
222.font = None
223};
224
225XClearWindow(MainDisplay, window);
226
227pos *p = arena_push(arena, sizeof(*p), 0);
228
229p->z = 10;
230p->x = ((i32)*pX * 10) / p->z;
231p->y = ((i32)*pY * 10) / p->z;
232
233XFillRectangle(
234MainDisplay,
235window,
236gc,
237(i32)p->x,
238(i32)p->y,
239rect_height,
240rect_width);
241
242m.move(&x);
243
244sleep_ms(1);
245
246XFlush(MainDisplay);
247}
248
249case DestroyNotify:
250{
251// handle_destroy(MainDisplay, &gc);
252}
253}
254
255arena_clear(arena);
256return 0;
257}
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..a113e23
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,8 @@
1#!/bin/sh
2set -eu
3
4build_dir=~/projects/tb/build
5
6# Run
7export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}:$build_dir"
8"$build_dir/app"
diff --git a/source/base/base.h b/source/base/base.h
new file mode 100755
index 0000000..5fcf9e2
--- /dev/null
+++ b/source/base/base.h
@@ -0,0 +1,77 @@
1#ifndef BASE_H
2#define BASE_H
3
4#include <stdint.h>
5#include <unistd.h>
6#include <stddef.h>
7#include <string.h>
8
9/* assert an expression and output the file and the line */
10
11#define internal static
12#define global_variable static
13#define local_persist static
14
15#define ERR_OK 0
16#define ERR_IO 1
17#define ERR_PARSE 2
18#define ERR_PERM 3
19#define ERR_INVALID 4
20
21#define KiB(n) (((u64)(n)) << 10)
22#define MiB(n) (((u64)(n)) << 20)
23#define GiB(n) (((u64)(n)) << 30)
24
25#define unused(x) (void)(x)
26
27#define PATH_MAX_LEN 128
28#define BUFF_SMALL 128
29#define BUFF_DEFAULT 256
30#define BUFF_LARGE 512
31
32#define NIL 0
33
34#define DEPRECATED __attribute__((__deprecated__))
35
36#if defined(__arm__) || defined(__aarch64__)
37#define breakpoint __asm__ volatile("brk #0");
38#define temp_breakpoint __asm__ volatile("udf #0");
39#elif defined(__i386__) || defined(__x86_64__)
40#define breakpoint __asm__ volatile("int3");
41#endif
42
43#define MemCpy(dest, src, len) memcpy((dest), (src), (len))
44#define MemSet(dest, len) memset((dest), (0), (len))
45
46typedef uint64_t u64;
47typedef uint32_t u32;
48typedef uint16_t u16;
49typedef uint8_t u8;
50
51typedef int8_t i8;
52typedef int16_t i16;
53typedef int32_t i32;
54typedef int64_t i64;
55
56typedef float f32;
57typedef double f64;
58
59typedef i32 b32;
60typedef i16 b16;
61typedef u8 b8;
62
63typedef uintptr_t umm;
64typedef intptr_t smm;
65
66#define TRUE (0 == 0)
67#define FALSE (0 != 0)
68
69typedef struct s8 s8;
70
71struct s8
72{
73 char *data;
74 umm size;
75};
76
77#endif
diff --git a/source/base/base_arena.c b/source/base/base_arena.c
new file mode 100755
index 0000000..76938bd
--- /dev/null
+++ b/source/base/base_arena.c
@@ -0,0 +1,142 @@
1internal mem_arena *
2arena_create(u64 capacity)
3{
4 mem_arena *arena = (mem_arena *)mmap(
5 /* kernel decides where to throw the arena */
6 NULL,
7 capacity + sizeof(mem_arena),
8 PROT_READ | PROT_WRITE,
9 MAP_SHARED | MAP_ANONYMOUS,
10 -1,
11 0);
12
13 if (arena == MAP_FAILED)
14 {
15 return NULL;
16 }
17
18 arena->capacity = capacity;
19 arena->base_position = (u8 *)arena + sizeof(mem_arena);
20 arena->current_position = 0;
21 arena->previous_position = 0;
22
23 return arena;
24}
25
26internal void
27arena_destroy(mem_arena *arena)
28{
29 if (!arena)
30 {
31 return;
32 }
33
34 int code = munmap(arena, arena->capacity + sizeof(mem_arena));
35}
36
37internal void *
38arena_alloc(mem_arena *arena, u64 size)
39{
40 if (!arena)
41 {
42 return NULL;
43 }
44
45 u64 aligned = Align(arena->current_position, ARENA_ALIGN);
46 u64 new_pos = aligned + size;
47
48 if (new_pos > arena->capacity)
49 {
50 return NULL;
51 }
52
53 void *out = arena->base_position + aligned;
54
55 arena->previous_position = arena->current_position;
56 arena->current_position = aligned + size;
57
58 MemSet(out, size);
59
60 return out;
61}
62
63internal void
64arena_pop(mem_arena *arena, u64 size)
65{
66 size = MIN(size, arena->current_position);
67 arena->current_position -= size;
68}
69
70internal void
71arena_pop_to(mem_arena *arena, u64 pos)
72{
73 u64 size = pos < arena->current_position ? arena->current_position - pos : 0;
74 arena_pop(arena, size);
75}
76
77internal void
78arena_clear(mem_arena *arena)
79{
80 arena->current_position = 0;
81}
82
83internal mem_arena *
84arena_resize_align(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size, umm alignment)
85{
86 u8 *old_mem = (u8 *)old_memory;
87
88 if (!is_pow(alignment))
89 {
90 Align(arena->current_position, alignment);
91 }
92
93 if (old_memory == NULL || old_size == 0)
94 {
95 return (mem_arena *)arena_alloc(arena, new_size);
96 }
97 else if ((old_mem >= arena->base_position && old_mem < arena->base_position + arena->capacity))
98 {
99 if ((arena->base_position + arena->previous_position) == old_memory)
100 {
101 arena->current_position = arena->previous_position + new_size;
102 if (new_size > old_size)
103 {
104 MemSet(&arena->current_position, new_size - old_size);
105 }
106 return (mem_arena *)old_memory;
107 }
108 else
109 {
110 void *new_memory = arena_alloc(arena, new_size);
111 umm copy_size = old_size < new_size ? old_size : new_size;
112 memmove(new_memory, old_mem, copy_size);
113 }
114 }
115 else
116 {
117 check(0);
118 }
119 return NULL;
120}
121
122internal mem_arena *
123arena_resize(mem_arena *arena, void *old_memory, u64 new_size, u64 old_size)
124{
125 return arena_resize_align(arena, old_memory, new_size, old_size, ARENA_ALIGN);
126}
127
128internal temp_arena
129temp_arena_begin(mem_arena *arena)
130{
131 temp_arena t;
132 t.arena = arena;
133 t.start_position = arena->current_position;
134
135 return t;
136}
137
138internal void
139temp_arena_end(temp_arena temp)
140{
141 temp.arena->current_position = temp.start_position;
142}
diff --git a/source/base/base_arena.h b/source/base/base_arena.h
new file mode 100755
index 0000000..71d9e69
--- /dev/null
+++ b/source/base/base_arena.h
@@ -0,0 +1,41 @@
1#ifndef ARENA_H
2#define ARENA_H
3
4#define Align(pointer, alignment) align((u64)(pointer), (umm)(alignment))
5#define PushStruct(arena, type) (type *)arena_alloc((arena), sizeof(type))
6#define PushArray(arena, type, len) (type *)arena_alloc((arena), sizeof(type) * (len))
7#define PushString(arena, len) (s8 *)arena_alloc((arena), sizeof(s8)*len))
8
9typedef struct mem_arena mem_arena;
10typedef struct temp_arena temp_arena;
11
12struct mem_arena
13{
14 u64 current_position;
15 u64 previous_position;
16 u64 capacity;
17 u8 *base_position;
18};
19
20struct temp_arena
21{
22 mem_arena *arena;
23 u64 start_position;
24};
25
26internal mem_arena *
27arena_resize_align(
28 mem_arena *arena,
29 void *old_memory,
30 u64 new_size,
31 u64 old_size,
32 umm alignment);
33
34internal mem_arena *
35arena_resize(
36 mem_arena *arena,
37 void *old_memory,
38 u64 new_size,
39 u64 old_size);
40
41#endif
diff --git a/source/base/base_hash.c b/source/base/base_hash.c
new file mode 100644
index 0000000..c309a9a
--- /dev/null
+++ b/source/base/base_hash.c
@@ -0,0 +1,18 @@
1
2internal u64
3generate_hash()
4{
5 // TODO(nasr):
6 return 0;
7}
8
9internal hash_map
10make_hash_map
11{
12
13 // TODO(nasr):
14
15 return {0};
16
17}
18
diff --git a/source/base/base_include.h b/source/base/base_include.h
new file mode 100755
index 0000000..3f83fd7
--- /dev/null
+++ b/source/base/base_include.h
@@ -0,0 +1,30 @@
1#ifndef BASE_INCLUDE_H
2#define BASE_INCLUDE_H
3
4#include <dirent.h>
5#include <sys/mman.h>
6#include <sys/stat.h>
7#include <fcntl.h>
8#include <stdint.h>
9#include <stddef.h>
10#include <string.h>
11#include <unistd.h>
12
13#include "base.h"
14#include "base_mem.h"
15#include "base_arena.h"
16#include "base_parse.h"
17#include "base_stack.h"
18#include "base_test.h"
19
20#if defined(TB_IMPLEMENTATION)
21
22#include "base_mem.c"
23#include "base_arena.c"
24#include "base_parse.c"
25#include "base_stack.c"
26#include "base_test.c"
27
28#endif
29
30#endif
diff --git a/source/base/base_mem.c b/source/base/base_mem.c
new file mode 100644
index 0000000..f20ba39
--- /dev/null
+++ b/source/base/base_mem.c
@@ -0,0 +1,17 @@
1internal inline b8
2is_pow(umm x)
3{
4 return (x & (x - 1)) == 0;
5}
6
7internal inline u64
8align(u64 pointer, umm alignment)
9{
10 if ((alignment & (alignment - 1)) == 0)
11 {
12 return pointer;
13 }
14
15 return (pointer + alignment - 1) & ~(alignment - 1);
16}
17
diff --git a/source/base/base_mem.h b/source/base/base_mem.h
new file mode 100644
index 0000000..945f0ce
--- /dev/null
+++ b/source/base/base_mem.h
@@ -0,0 +1,8 @@
1#ifndef BASE_MEM_H
2#define BASE_MEM_H
3
4#define ARENA_ALIGN (2 * sizeof(void *))
5#define MIN(a, b) (((a) < (b)) ? (a) : (b))
6#define MAX(a, b) (((a) > (b)) ? (a) : (b))
7
8#endif
diff --git a/source/base/base_parse.c b/source/base/base_parse.c
new file mode 100755
index 0000000..4f216bf
--- /dev/null
+++ b/source/base/base_parse.c
@@ -0,0 +1,98 @@
1/*
2 * is_numeric - Check if a string contains only digits
3 * @s: String to check
4 *
5 * Return: 1 if string contains only numeric characters, 0 otherwise
6 */
7internal b8
8is_numeric(char *s)
9{
10 for (; *s; ++s)
11 {
12 if (*s < '0' || *s > '9')
13 {
14 return 0;
15 }
16 }
17 return 1;
18}
19
20/*
21 * TODO(nasr): checkout i think there is a buffer overflow happening somewhere
22 * */
23internal proc_file *
24parse_proc_files(char *path, mem_arena *arena)
25{
26 if (!path || !arena)
27 {
28 return NULL;
29 }
30
31 i32 fd = open(path, O_RDONLY);
32 if (fd < 0)
33 {
34 return NULL;
35 }
36
37 char *buffer = PushArray(arena, char, KiB(4));
38 u64 bytes = read(fd, buffer, KiB(4));
39 close(fd);
40
41 if (bytes == 0)
42 {
43 return NULL;
44 }
45
46 /* guessing the count to 256 because i dont want to do a double pass of the buffer */
47 proc_file *pf = PushStruct(arena, proc_file);
48 pf->entries = PushArray(arena, proc_entry, 256);
49
50 u64 line_start = 0;
51 u64 delim = -1;
52 u64 entry_index = 0;
53
54 for (u64 index = 0; index < bytes; ++index)
55 {
56 if (buffer[index] == ':' && delim == (u64)-1)
57 {
58 delim = index;
59 }
60 else if (buffer[index] == '\n')
61 {
62 if (delim != (-1.f))
63 {
64 u64 key_len = delim - line_start;
65 if (key_len >= sizeof(pf->entries[entry_index].key))
66 {
67 key_len = sizeof(pf->entries[entry_index].key) - 1;
68 }
69
70 u64 val_start = delim + 1;
71 while (val_start < index && (buffer[val_start] == ' ' || buffer[val_start] == '\t'))
72 {
73 val_start++;
74 }
75
76 u64 val_len = index - val_start;
77 if (val_len >= sizeof(pf->entries[entry_index].value))
78 {
79 val_len = sizeof(pf->entries[entry_index].value) - 1;
80 }
81
82 MemCpy(pf->entries[entry_index].key, buffer + line_start, key_len - 1);
83 MemCpy(pf->entries[entry_index].value, buffer + val_start, val_len);
84
85 pf->entries[entry_index].key[key_len] = '\0';
86 pf->entries[entry_index].value[val_len] = '\0';
87
88 ++pf->count;
89 ++entry_index;
90 }
91
92 line_start = index + 1;
93 delim = (u64)-1;
94 }
95 }
96
97 return (pf);
98}
diff --git a/source/base/base_parse.h b/source/base/base_parse.h
new file mode 100755
index 0000000..d66fd04
--- /dev/null
+++ b/source/base/base_parse.h
@@ -0,0 +1,28 @@
1#ifndef BASE_PARSE_H
2#define BASE_PARSE_H
3
4#define COMPARE_STRING(c1, c2) compare_string((char *)c1, (char *)c2)
5
6typedef struct proc_entry proc_entry;
7typedef struct proc_file proc_file;
8
9struct proc_file
10{
11 i32 count;
12 proc_entry *entries;
13};
14
15struct proc_entry
16{
17 char value[16];
18 char key[16];
19};
20
21typedef struct
22{
23 i8 *start;
24 i8 *end;
25 umm len;
26} Line;
27
28#endif
diff --git a/source/base/base_stack.c b/source/base/base_stack.c
new file mode 100755
index 0000000..7cf0570
--- /dev/null
+++ b/source/base/base_stack.c
@@ -0,0 +1,187 @@
1internal mem_stack *
2stack_create(u64 capacity)
3{
4 mem_stack *stack = (mem_stack *)mmap(
5 0,
6 capacity + sizeof(mem_stack),
7 PROT_READ | PROT_WRITE,
8 MAP_SHARED | MAP_ANONYMOUS,
9 -1,
10 0);
11
12 if (stack == MAP_FAILED)
13 {
14 return NULL;
15 }
16
17 stack->capacity = capacity;
18 stack->base_position = (u8 *)stack + sizeof(mem_stack);
19 stack->current_offset = 0;
20
21 return stack;
22}
23
24internal umm
25calculate_padding(umm pointer, umm alignment, umm header_size)
26{
27 umm modulo, padding;
28
29 if (!is_pow(alignment))
30 {
31 return 0;
32 }
33
34 modulo = pointer & (alignment - 1);
35
36 padding = 0;
37
38 if (0 == modulo)
39 {
40 padding = alignment - modulo;
41 }
42
43 if (padding < header_size)
44 {
45 header_size -= padding;
46
47 if ((header_size & (alignment - 1)) != 0)
48 {
49 padding += alignment * (1 + (header_size / alignment));
50 }
51 else
52 {
53 padding += alignment * (header_size / alignment);
54 }
55 }
56
57 return padding;
58}
59
60internal mem_stack *
61stack_push_align(mem_stack *stack, u64 size, umm alignment)
62{
63 umm padding = 0;
64
65 if (!is_pow(alignment))
66 {
67 return (0);
68 }
69
70 if (alignment > 128)
71 {
72 alignment = 128;
73 }
74
75 umm current_address = (umm)stack->base_position + stack->current_offset;
76 padding = calculate_padding(current_address, alignment, sizeof(mem_stack_header));
77
78 if (stack->current_offset + padding + size > stack->capacity)
79 {
80 return 0;
81 }
82
83 stack->current_offset += padding;
84
85 umm next_address = current_address + (umm)padding;
86 mem_stack_header *header = (mem_stack_header *)(next_address - sizeof(mem_stack_header));
87 header->padding = padding;
88
89 stack->current_offset += size;
90
91 return MemSet((void *)next_address, size);
92}
93internal void *
94stack_push(mem_stack *stack, umm size)
95{
96 return stack_push_align(stack, size, ARENA_ALIGN);
97}
98
99internal void
100stack_pop(mem_stack *stack, void *pointer)
101{
102 if (pointer != NULL)
103 {
104 umm start, end, current_address;
105 mem_stack_header *header;
106 umm prev_offset;
107
108 start = (umm)stack->base_position;
109 end = start + (umm)stack->capacity;
110 current_address = (umm)pointer;
111
112 if (!(start <= current_address && current_address < end))
113 {
114 if (0 && "Out of bounds memory address passed to stack allocator (free)")
115 {
116 return;
117 }
118 return;
119 }
120
121 if (current_address >= start + (umm)stack->base_position)
122 {
123 return;
124 }
125
126 header = (mem_stack_header *)(current_address - sizeof(mem_stack_header));
127 prev_offset = (size_t)(current_address - (umm)header->padding - start);
128 stack->current_offset = prev_offset;
129 }
130}
131
132internal mem_stack *
133stack_resize_align(mem_stack *stack, void *pointer, u64 old_size, u64 new_size, u64 alignment)
134{
135 if (pointer == NULL)
136 {
137 return stack_push_align(stack, new_size, alignment);
138 }
139 else if (new_size == 0)
140 {
141 stack_pop(stack, pointer);
142 return NULL;
143 }
144
145 umm start, end, current_address;
146 umm min_size = old_size < new_size ? old_size : new_size;
147 void *new_pointer;
148
149 start = (umm)stack->base_position;
150 end = start + (umm)stack->capacity;
151 current_address = (umm)pointer;
152 if (!(start <= current_address && current_address < end))
153 {
154 return NULL;
155 }
156
157 if (current_address >= start + (umm)stack->current_offset)
158 {
159 return NULL;
160 }
161
162 if (old_size == new_size)
163 {
164 return pointer;
165 }
166
167 new_pointer = stack_push_align(stack, new_size, alignment);
168 memmove(new_pointer, pointer, min_size);
169 return new_pointer;
170}
171
172internal void
173stack_pop_all(mem_stack *stack)
174{
175 stack->current_offset = 0;
176}
177
178internal void
179stack_destroy(mem_stack *stack)
180{
181 if (!stack)
182 {
183 return;
184 }
185
186 munmap(stack, stack->capacity + sizeof(mem_stack));
187}
diff --git a/source/base/base_stack.h b/source/base/base_stack.h
new file mode 100755
index 0000000..fc80b20
--- /dev/null
+++ b/source/base/base_stack.h
@@ -0,0 +1,20 @@
1#ifndef STACK_H
2#define STACK_H
3
4typedef struct mem_stack mem_stack;
5typedef struct mem_stack_header mem_stack_header;
6
7struct mem_stack
8{
9 u8 *base_position;
10 umm current_offset;
11 umm capacity;
12};
13
14struct mem_stack_header
15{
16 u8 padding;
17 u8 previous_offset;
18};
19
20#endif
diff --git a/source/base/base_string.c b/source/base/base_string.c
new file mode 100644
index 0000000..cb2d71d
--- /dev/null
+++ b/source/base/base_string.c
@@ -0,0 +1,73 @@
1internal umm
2skip_whitespaces(string *buffer)
3{
4 s32 index = 0;
5 while (buffer->size > index)
6 {
7 ++index;
8 }
9}
10
11internal b8
12compare_string_struct(string c1, string c2)
13{
14 if (c1.size != c2.size)
15 {
16 return -1;
17 }
18
19 for (s32 index = 0;
20 index < c1.size;
21 ++index)
22 {
23 if (c1.Data[index] != c2.Data[index])
24 {
25 return -1;
26 }
27 }
28
29 return 0;
30}
31
32internal b8
33compare_string(char *c1, char *c2)
34{
35 if (sizeof(*c1) != sizeof(*c2))
36 {
37 return -1;
38 }
39
40 for (
41 u64 word_idx = 0;
42 word_idx <= sizeof(*c1);
43 ++word_idx)
44 {
45 if (*c1 != *c2)
46 {
47 return -1;
48 }
49 ++c1;
50 ++c2;
51 }
52
53 return 0;
54}
55
56/** NOTE(nasr): Helper function to parse strings to int using ascii codes **/
57internal u64
58parse_u64(char *buf, umm len)
59{
60 u64 value = 0;
61
62 for (umm buffer_idx = 0; buffer_idx < len; ++buffer_idx)
63 {
64 char c = buf[buffer_idx];
65 if (c < '0' || c > '9')
66 {
67 break;
68 }
69 value = value * 10 + (c - '0');
70 }
71
72 return value;
73}
diff --git a/source/base/base_string.h b/source/base/base_string.h
new file mode 100644
index 0000000..d879450
--- /dev/null
+++ b/source/base/base_string.h
@@ -0,0 +1,17 @@
1#ifndef BASE_STRING_H
2#define BASE_STRING_H
3
4// let's use this for strings
5// to better differentiate between stuff
6typedef u8 s8;
7typedef struct string string ;
8
9struct string
10{
11 s8 *data;
12 umm size;
13};
14
15// TODO(nasr): helper functions for string
16
17#endif /* BASE_STRING_H */
diff --git a/source/base/base_test.c b/source/base/base_test.c
new file mode 100644
index 0000000..e44aa69
--- /dev/null
+++ b/source/base/base_test.c
@@ -0,0 +1,14 @@
1void
2write_int(i32 num)
3{
4 if (num < 0)
5 {
6 write(STDERR_FILENO, "-", 1);
7 num = -num;
8 }
9 if (num >= 10)
10 write_int(num / 10);
11 char digit = '0' + (num % 10);
12
13 write(STDERR_FILENO, &digit, 1);
14}
diff --git a/source/base/base_test.h b/source/base/base_test.h
new file mode 100644
index 0000000..11028f4
--- /dev/null
+++ b/source/base/base_test.h
@@ -0,0 +1,61 @@
1#ifndef BASE_TEST_H
2#define BASE_TEST_H
3
4void
5write_int(i32 num);
6
7#define RED "\x1b[31m"
8#define GREEN "\x1b[32m"
9#define RESET "\x1b[0m"
10#define BLUE "\x1b[34m"
11
12#define LEN(s) (sizeof(s) - 1)
13
14#define show \
15 do \
16 { \
17 write(STDOUT_FILENO, __FILE__, sizeof(__FILE__) - 1); \
18 write(STDOUT_FILENO, ":", 1); \
19 write(STDOUT_FILENO, __func__, sizeof(__func__) - 1); \
20 write(STDOUT_FILENO, ":", 1); \
21 write_int(__LINE__); \
22 write(STDOUT_FILENO, "\n", 1); \
23 } while (0)
24
25#define test(expr) \
26 { \
27 if ((expr) != 0) \
28 { \
29 write(STDERR_FILENO, "[FAILED] ", LEN("[FAILED] ")); \
30 show; \
31 _exit(1); \
32 } \
33 }
34
35#define check(expr) \
36 { \
37 if ((expr) != 0) \
38 { \
39 write(STDERR_FILENO, RED "[ERROR] ", LEN(RED "[ERROR] ")); \
40 show; \
41 write(STDERR_FILENO, RESET, LEN(RESET)); \
42 _exit(1); \
43 } \
44 else \
45 { \
46 write(STDERR_FILENO, GREEN "[SUCCESS] ", LEN(GREEN "[SUCCESS] ")); \
47 show; \
48 write(STDERR_FILENO, RESET, LEN(RESET)); \
49 } \
50 }
51
52#define checkpoint_output "<<CHECKPOINT>>\n"
53#define checkpoint_end_output "^^^^^^^^^^^^^^\n\n\n"
54#define checkpoint \
55 { \
56 write(STDERR_FILENO, BLUE checkpoint_output, LEN(BLUE checkpoint_output)); \
57 show; \
58 write(STDERR_FILENO, BLUE checkpoint_end_output, LEN(BLUE checkpoint_end_output)); \
59 }
60
61#endif /* BASE_TEST_H */
diff --git a/source/base/bash_hash.h b/source/base/bash_hash.h
new file mode 100644
index 0000000..2c286a2
--- /dev/null
+++ b/source/base/bash_hash.h
@@ -0,0 +1,15 @@
1##ifndef HEADER_H
2#define HEADER_H
3
4typedef struct hash_map hash_map;
5typedef struct hash hash;
6
7
8struct hash_map
9{
10
11
12};
13
14
15#endif /* HEADER_H */
diff --git a/source/core/core.c b/source/core/core.c
new file mode 100644
index 0000000..43322de
--- /dev/null
+++ b/source/core/core.c
@@ -0,0 +1,126 @@
1#define TB_IMPLEMENTATION
2#include "core.h"
3#include "../base/base_include.h"
4#include "../platform/platform_include.h"
5
6int main()
7{
8 b32 running = 1;
9
10 Display *MainDisplay = XOpenDisplay(0);
11 mem_arena *arena = arena_create(MiB(8));
12
13 Window root = XDefaultRootWindow(MainDisplay);
14 int screen = DefaultScreen(MainDisplay);
15
16 Visual *v = DefaultVisual(MainDisplay, screen);
17
18 XSetWindowAttributes wa = {
19 .background_pixmap = None,
20 .background_pixel = BlackPixel(MainDisplay, DefaultScreen(MainDisplay)),
21 .border_pixmap = CopyFromParent,
22 .border_pixel = 0,
23 .bit_gravity = ForgetGravity,
24 .win_gravity = NorthWestGravity,
25 .backing_store = NotUseful,
26 .backing_planes = 1,
27 .backing_pixel = 0,
28 .save_under = False,
29 .event_mask = 0,
30 .do_not_propagate_mask = 0,
31 .override_redirect = False,
32 .colormap = CopyFromParent,
33 .cursor = None
34 };
35
36 i32 dp_heigth = DisplayHeight(MainDisplay, screen);
37 i32 dp_width = DisplayWidth(MainDisplay, screen);
38
39 WindowProperties p = {
40
41 .x = dp_width / 2,
42 .y = dp_heigth / 2,
43 .height = (u32)800,
44 .width = (u32)1200,
45 .border_width = 0,
46 .window_depth = CopyFromParent,
47 .window_class = CopyFromParent,
48 .value_mask = CWBackPixel,
49
50 };
51
52 Window window =
53 XCreateWindow(
54 MainDisplay,
55 root,
56 p.x,
57 p.y,
58 p.width,
59 p.height,
60 p.border_width,
61 p.window_depth,
62 p.window_class,
63 v,
64 p.value_mask,
65 &wa);
66
67 Pixmap pixmap = XCreatePixmap(MainDisplay, window, dp_width, dp_heigth, 1);
68
69 XSetWindowBorder(MainDisplay, window, 60);
70
71 // NOTE(nasr): type of input we want to handle
72 XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask | KeyReleaseMask);
73
74 XMapWindow(MainDisplay, window);
75
76 double x = p.width / 2;
77 double y = p.height / 2;
78
79 u32 rect_width = 50;
80 u32 rect_height = 50;
81
82 u64 color = 0x0000ff00;
83
84 GC gc = XCreateGC(MainDisplay, window, 0, NIL);
85 XSetForeground(MainDisplay, gc, color);
86
87 double *pX = &x;
88 double *pY = &y;
89
90 XEvent event;
91 XNextEvent(MainDisplay, &event);
92
93 for (;running;)
94 {
95 KeySym keysym = XLookupKeysym(event, 0);
96
97 switch (event.type)
98 {
99 case (KeyPress):
100 {
101 if (keysym == XK_p || keysym == XK_P)
102 {
103 XDrawRectangle(MainDisplay, screen, gc, 50, 50, 50, 50);
104 }
105
106 break;
107 }
108 case (KeyRelease):
109 {
110 if (keysym == XK_p || keysym == XK_P)
111 {
112 XDrawRectangle(MainDisplay, screen, gc, 50, 50, 50, 50);
113 }
114
115 break;
116 }
117 default:
118 {
119
120 }
121
122 }
123 }
124 arena_clear(arena);
125 return 0;
126}
diff --git a/source/core/core.h b/source/core/core.h
new file mode 100644
index 0000000..c5821c5
--- /dev/null
+++ b/source/core/core.h
@@ -0,0 +1,5 @@
1#ifndef CORE_H
2#define CORE_H
3
4
5 #endif
diff --git a/source/platform/platform.c b/source/platform/platform.c
new file mode 100644
index 0000000..2e7bbad
--- /dev/null
+++ b/source/platform/platform.c
@@ -0,0 +1,12 @@
1internal inline void
2sleep_ms(long ms)
3{
4 struct timespec ts;
5 ts.tv_sec = ms / 1000;
6 ts.tv_nsec = (ms % 1000) * 1000000L;
7
8 while (nanosleep(&ts, &ts))
9 {
10 NULL;
11 }
12}
diff --git a/source/platform/platform.h b/source/platform/platform.h
new file mode 100644
index 0000000..da8e065
--- /dev/null
+++ b/source/platform/platform.h
@@ -0,0 +1,56 @@
1#ifndef PLATFORM_H
2#define PLATFORM_H
3
4#define NIL 0
5
6#include <X11/X.h>
7#include <X11/Xlib.h>
8 #include <X11/keysym.h>
9#include <time.h>
10#include <unistd.h>
11
12typedef struct WindowProperties WindowProperties;
13struct WindowProperties
14{
15 i32 x;
16 i32 y;
17 u32 height;
18 u32 width;
19 u32 border_width;
20 i32 window_depth;
21 u32 window_class;
22 u64 value_mask;
23
24};
25
26typedef struct vertex vertex;
27
28struct vertex
29{
30 i32 x;
31 i32 y;
32 i32 z;
33};
34
35typedef struct display_pos display_pos;
36
37struct display_pos
38{
39 i32 x;
40 i32 y;
41
42};
43
44typedef struct pos pos;
45struct pos
46{
47 i32 x;
48 i32 y;
49 i32 z;
50
51} ;
52
53
54
55
56#endif /* PLATFORM_H */
diff --git a/source/platform/platform_include.h b/source/platform/platform_include.h
new file mode 100644
index 0000000..886c6b8
--- /dev/null
+++ b/source/platform/platform_include.h
@@ -0,0 +1,7 @@
1#ifndef PLATFORM_INCLUDE_H
2#define PLATFORM_INCLUDE_H
3
4#include "platform.h"
5#include "platform.c"
6
7#endif /* PLATFORM_INCLUDE_H */
diff --git a/xlib-tutorial/2nd-program-anatomy.html b/xlib-tutorial/2nd-program-anatomy.html
deleted file mode 100644
index d156f7a..0000000
--- a/xlib-tutorial/2nd-program-anatomy.html
+++ /dev/null
@@ -1,282 +0,0 @@
1<HTML>
2<HEAD>
3<TITLE>Xlib programming tutorial: anatomy of the most basic Xlib program</TITLE>
4</HEAD>
5
6<BODY>
7<H1 ALIGN=center>Anatomy of the most basic Xlib program</H1>
8
9The program starts with the legal stuff:
10
11<PRE><CODE>
12#include &lt;X11/Xlib.h&gt; // Every Xlib program must include this
13#include &lt;assert.h&gt; // I include this to test return values the lazy way
14#include &lt;unistd.h&gt; // So we got the profile for 10 seconds
15
16#define NIL (0) // A name for the void pointer
17</PRE></CODE>
18
19Then the serious thing. First we open a connection to the server.
20
21<PRE><CODE>
22Display *dpy = XOpenDisplay(NIL);
23assert(dpy);
24</PRE></CODE>
25
26If it fails (and it may), <B><A HREF="/gui/x/xlib/display/opening.html">XOpenDisplay()</A></B> will return NIL.
27
28<P>
29
30We gonna create a window, but we need to get the window's background
31color first. X uses a quite complex color model in order to accommodate
32to every conceivable piece of hardware. Each color is encoded by an integer,
33but the integer for a given color may change from a machine to another
34one, and even on the same machine, from an execution of the program to
35the next. The only "colors" that X guarantees to exist are black and
36white. We can get them using the
37<B><A HREF="/gui/x/xlib/display/display-macros.html#BlackPixel">BlackPixel()</A></B>
38and
39<B><A HREF="/gui/x/xlib/display/display-macros.html#WhitePixel">WhitePixel()</A></B>
40macros.
41
42<PRE><CODE>
43 int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
44 int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
45</PRE></CODE>
46
47As we yet can see, most of the Xlib calls take the "display" (the
48value returned by
49<B><A HREF="/gui/x/xlib/display/opening.html">XOpenDisplay()</A></B>)
50as their first parameter. <A HREF="server.html">You want to know why ?</A>
51
52<P>
53
54There is still someting magic, (the
55<B><A HREF="/gui/x/xlib/display/display-macros.html#DefaultScreen">DefaultScreen()</A></B>
56stuff), but we gonna keep it for a <A HREF="screen-and-root-window.html">later
57explanation</A>. We now can
58create our window:
59
60<PRE><CODE>
61 // Create the window
62
63 Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
64 200, 100, 0, blackColor, blackColor);
65</PRE></CODE>
66
67Unlike what appears in the <A HREF="./">dialog</A>, we use the
68function
69<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
70instead of
71<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>.
72<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
73is not really simpler than
74<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>
75(it takes only a few less parameters), but it uses less concepts, so
76we gonna stick to it for now. There are still a bunch of parameters to
77explain:
78
79<UL>
80
81<LI> <CODE>dpy</CODE> is the usual display connection (<A HREF="server.html">remember</A>).
82
83<P><LI> <CODE>DefaultRootWindow(dpy)</CODE>: yet another parameter that may
84seem magic until now. This is the "parent window" of the window we are
85creating. The window we create appears inside its parent, and is
86bounded by it (the window is said to be "clipped" by its
87parent). Those who guess from the name "Default" that they may be
88other root windows guess right. More on this <A
89HREF="screen-and-root-window.html">later</A>. For now, the default
90root window makes appear our window on the screen, and will give the
91<A HREF="window-manager.html">window manager</A> a chance to decorate
92our window.
93
94<P><LI> <CODE>0, 0</CODE> These are the coordinates of the upper left
95corner of the window (the origin of the coordinates in X is at the
96upper left, contrary to most mathematical textbooks). The dimensions,
97like every dimensions in X, are in pixels (X does not support
98user-defined scales, unlike some other graphical systems like
99<A HREF="/web-directory/science-and-technology/computer/graphics/">OpenGL</A>).
100
101<P>
102
103Contrary to what may seem, there is very little chance for the window
104to appear, at 0,0. The reason is that the
105<A HREF="window-manager.html">window manager</A> will put the window
106at its policy-defined position.
107
108<P><LI> <CODE>200, 100</CODE>: these are the width and height of the
109window, in pixels.
110
111<P><LI> <CODE>0</CODE>: this is the width of the window's border. This
112has nothing to do with the border appended by the
113<A HREF="window-manager.html">window manager</A>, so this is most
114often set to zero.
115
116<P><LI> <CODE>blackColor, blackColor</CODE>: these are the colors of the
117window's border (NOT the
118<A HREF="window-manager.html">window manager</A>'s border), and the
119window's background, respectively.
120<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateSimpleWindow()</A></B>
121clears the window when created,
122<B><A HREF="/gui/x/xlib/window/XCreateWindow.html">XCreateWindow()</A></B>
123does not.
124
125</UL>
126
127<PRE><CODE>
128 // We want to get MapNotify events
129
130 XSelectInput(dpy, w, StructureNotifyMask);
131</PRE></CODE>
132
133As we're starting to know, X is based upon a
134<A HREF="server.html">client-server</A> architecture. The X server
135sends events to the client (the program we're writing), to keep it
136informed of the modifications in the server. There are many of them
137(each time a window is created, moved, masked, unmasked, and many
138other things), so a client must tell the server the events it is
139interested in. With this <B>XSelectInput()</B> stuff, we tell the
140server we want to be informed of "structural" changes occuring on the
141<TT>w</TT> window. Creation and mapping are such changes. There is no
142way to be informed for example of only mapping modification, and not
143creations, so we've to take everything. In this particular application
144we're interesting in "mapping" events (<I>grosso modo</I>, the window
145appears on the screen).
146
147<PRE><CODE>
148 // "Map" the window (that is, make it appear on the screen)
149
150 XMapWindow(dpy, w);
151</PRE></CODE>
152
153And (once again) this is a <A HREF="server.html">client-server</A>
154system. The map request is asynchronous, meaning that the time this
155instruction is executed doesn't tell us when the window is actually
156mapped. To be sure, we've to wait for the server to send us a
157<B><A HREF="/gui/x/xlib/events/window-state-change/map.html">MapNotify</A></B>
158event (this is why we want to be sensitive to such events).
159
160<PRE><CODE>
161 // Create a "Graphics Context"
162
163 GC gc = XCreateGC(dpy, w, 0, NIL);
164</PRE></CODE>
165
166Yet another magic stuff. But mastering them is the reason of the
167existence of this tutorial...
168
169<P>
170
171For several reasons, the graphical model of X is stateless, meaning
172that the server doesn't remember (among other things) attributes such
173as the drawing color, the thickness of the lines and so on. Thus,
174we've to give <EM>all these parameters</EM> to the server on each
175drawing request. To avoid passing two dozens of parameters, many of
176them unchanged from one request to the next, X uses an object called
177the <B>Graphics Context</B>, or <B>GC</B> for short. We store in the
178graphics context all the needed parameters. Here, we want the color
179used to draw lines, called the foregound color:
180
181<PRE><CODE>
182 // Tell the GC we draw using the white color
183
184 XSetForeground(dpy, gc, whiteColor);
185</PRE></CODE>
186
187There are many other parameters used to draw a line, but all of them
188have reasonable default values.
189
190<P>
191
192That's okay for now. Everything is set up, and we wait for the window
193mapping.
194
195<PRE><CODE>
196 // Wait for the MapNotify event
197
198 for(;;) {
199 XEvent e;
200 XNextEvent(dpy, &e);
201 if (e.type == MapNotify)
202 break;
203 }
204</PRE></CODE>
205
206We loop, taking events as they come and discarding them. When we get a
207<B>MapNotify</B>, we exit the loop. We may get events other than
208<B>MapNotify</B> for two reasons:
209
210<UL>
211<LI> We have selected <B>StructureNotifyMask</B> to get
212<B>MapNotify</B> events, but we could get other events as well (such
213as <B>ConfigureNotify</B>, telling the window has changed in position, and/or
214size).
215<LI> Some events can be received, even if we don't have asked for
216them, they are called "non-maskable". <B>GraphicsExpose</B> is such an
217event.
218</UL>
219
220The non-maskable events are sent only in response to some program
221requests (such as copying an area), so they aren't likely to happen in
222our context.
223
224<P>
225
226The
227<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>
228procedure is blocking, so if there are no event to read, the program
229just wait inside the
230<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>.
231
232<P>
233
234When we have exited the loop, we have good confidence that the window
235appears on the screen. Actually, this may not be the case since, for
236example, the user may have iconified it using the
237<A HREF="window-manager.html">window manager</A>, but for now, we assume the window
238actually appears. We can draw our line:
239
240<PRE><CODE>
241 // Draw the line
242
243 XDrawLine(dpy, w, gc, 10, 60, 180, 20);
244</PRE></CODE>
245
246The line is between points (10, 60) and (180, 20). The (0,0) is at the
247upper left corner of the window, as usual. If the program just
248<TT>sleep</TT>s here, nothing will happen, because, in case you don't
249know, X has a <A HREF="server.html">client-server</A>
250architecture. Thus the request stays in the client, unless we tell it
251to go to the server. This is done by <B><A
252HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>:
253
254<PRE><CODE>
255 // Send the "DrawLine" request to the server
256
257 XFlush(dpy);
258</PRE></CODE>
259
260Clever readers may have noticed that we didn't use
261<B><A HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>
262before, and it didn't prevent all the requests such as
263<B><A HREF="/gui/x/xlib/window/XMapWindow.html">XMapWindow()</A></B>
264to be sent to the server. The answer is that
265<B><A HREF="/gui/x/xlib/event-handling/manipulating-event-queue/XNextEvent.html">XNextEvent()</A></B>
266performs an implicit
267<B><A HREF="/gui/x/xlib/event-handling/XFlush.html">XFlush()</A></B>
268before trying to read some events. We have our line now, we just wait
269for 10 seconds, so we can make people see how beautiful is our work:
270
271<PRE><CODE>
272 // Wait for 10 seconds
273
274 sleep(10);
275</PRE></CODE>
276
277That's all for now. In <!A HREF="more-interaction.html"><B>next
278lesson</B></A>, we will have a (very) little more interaction. [to be continued]
279
280<HR><ADDRESS><A HREF="http://tronche.com/">Christophe Tronche</A>, <A HREF="mailto:ch.tronche@computer.org">ch.tronche@computer.org</A></ADDRESS>
281</BODY>
282</HTML>
diff --git a/xlib-tutorial/Xlib.pdf b/xlib-tutorial/Xlib.pdf
deleted file mode 100644
index cef1647..0000000
--- a/xlib-tutorial/Xlib.pdf
+++ /dev/null
Binary files differ
diff --git a/xlib-tutorial/index.html b/xlib-tutorial/index.html
deleted file mode 100644
index 5e57eaf..0000000
--- a/xlib-tutorial/index.html
+++ /dev/null
@@ -1,116 +0,0 @@
1<HTML>
2<HEAD>
3<TITLE>Xlib programming: a short tutorial</TITLE>
4</HEAD>
5
6<BODY>
7
8<H1>Xlib programming: a short tutorial</H1>
9
10I haven't found anything very satisfying on the Web as an Xlib
11tutorial. Many of them are too much Motif-oriented for my
12taste. Furthermore, I answer questions about X programming almost
13daily, so I've started to put together some small coursewares.
14
15<H4>Important note:</H4> the example programs are written in C++, but
16this is mainly for the ability to declare variables anywhere.
17
18<HR>
19
20Let's begin with a short story: the eternal story of the newbie at
21Xlib writing his/her first program.
22
23<P>
24
25<I>
26"Ok, I've to open a connection to the X server (whatever this means),
27with XOpenDisplay, then create a window with XCreateWindow, then draw
28a line with XDrawLine. Then, the program sleeps for ten seconds so I
29can see the result. Sounds easy."
30</I>
31
32<P>
33
34The poor newbie writes the program. And nothing happens. He then
35calls his wizard friend.
36
37<P>
38
39<I>
40-"Did you perform an XFlush after you've done everything ?<BR>
41- No, why ?<BR>
42- The requests stay in the client," </I>wizard doubletalk, thinks the
43poor newbie<I>, " if you
44don't."
45</I>
46
47<P>
48
49The poor newbie changes the program. And nothing happens. He then
50calls his wizard friend.
51
52<P>
53
54<I>
55-"Did you map your window ?<BR>
56- Did I do what ???<BR>
57- Creating a window doesn't make it appear on the screen. You've to
58 map it with XMapWindow first.
59</I>
60
61<P>
62
63The poor newbie changes the program. The window appears with nothing
64in it (<A HREF="prog-1.cc">like this</A>). The poor newbie then calls
65his wizard friend.
66
67<P>
68
69<I>
70-"Did you wait for a MapNotify before drawing your line ?" </I>(more wizard doubletalk)<I><BR>
71- "No, why ?</BR>
72- X has a stateless drawing model, the content of the window may be lost
73 when the window isn't on the screen." </I>(overflow, why can't these
74 wizard guys speak just like you and me ?)<I> "You've to wait for a MapNotify
75 before drawing."
76</I>
77
78<P>
79
80The poor newbie changes the program. Things are getting more and more
81complex. Not as easy as it first seemed. A loop gets the events until a
82MapNotify. The window appears with nothing
83in it. The poor newbie then calls his wizard friend.
84
85<P>
86
87<I>
88-"I got it, did you select the StructureNotifyMask on your window ?<BR>
89- ???<BR>
90- Just do it, and everything'll be fine.
91</I>
92
93<P>
94
95The poor newbie fixes the program. And the miracle happens ! A line in the
96window. Until now, the program looks like <A HREF="prog-2.cc">this</A>
97(it is actually slighty more complex than the dialog may let you think).
98
99<P>
100
101Now you've learned at least 2 things:
102
103<UL>
104<LI> How to draw a line in a window with X.
105<LI> Why some may need an X tutorial.
106</UL>
107
108Now, if you want to learn more and get a deeper understanding of the
109program, go to <A HREF="2nd-program-anatomy.html">next lesson</A>.
110
111<H4><A HREF="/gui/x/">More about X</A>.</H4>
112
113
114<HR><ADDRESS><A HREF="http://tronche.com/">Christophe Tronche</A>, <A HREF="mailto:ch.tronche@computer.org">ch.tronche@computer.org</A></ADDRESS>
115</BODY>
116</HTML>
diff --git a/xlib-tutorial/prog-1.cc b/xlib-tutorial/prog-1.cc
deleted file mode 100644
index 3ba596b..0000000
--- a/xlib-tutorial/prog-1.cc
+++ /dev/null
@@ -1,29 +0,0 @@
1// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
2// Copyright by the author. This is unmaintained, no-warranty free software.
3// Please use freely. It is appreciated (but by no means mandatory) to
4// acknowledge the author's contribution. Thank you.
5// Started on Thu Jun 26 23:29:03 1997
6
7//
8// Xlib tutorial: 1st program
9// Make a window appear on the screen.
10//
11
12#include <X11/Xlib.h> // Every Xlib program must include this
13#include <assert.h> // I include this to test return values the lazy way
14#include <unistd.h> // So we got the profile for 10 seconds
15
16#define NIL (0) // A name for the void pointer
17
18main()
19{
20 Display *dpy = XOpenDisplay(NIL);
21 assert(dpy);
22 Window w = XCreateWindow(dpy, DefaultRootWindow(dpy), 0, 0,
23 200, 100, 0,
24 CopyFromParent, CopyFromParent, CopyFromParent,
25 NIL, 0);
26 XMapWindow(dpy, w);
27 XFlush(dpy);
28 sleep(10);
29}
diff --git a/xlib-tutorial/prog-2.cc b/xlib-tutorial/prog-2.cc
deleted file mode 100644
index 51ea0e9..0000000
--- a/xlib-tutorial/prog-2.cc
+++ /dev/null
@@ -1,74 +0,0 @@
1// Written by Ch. Tronche (http://tronche.lri.fr:8000/)
2// Copyright by the author. This is unmaintained, no-warranty free software.
3// Please use freely. It is appreciated (but by no means mandatory) to
4// acknowledge the author's contribution. Thank you.
5// Started on Thu Jun 26 23:29:03 1997
6
7//
8// Xlib tutorial: 2nd program
9// Make a window appear on the screen and draw a line inside.
10// If you don't understand this program, go to
11// http://tronche.lri.fr:8000/gui/x/xlib-tutorial/2nd-program-anatomy.html
12//
13
14#include <X11/Xlib.h> // Every Xlib program must include this
15#include <assert.h> // I include this to test return values the lazy way
16#include <unistd.h> // So we got the profile for 10 seconds
17
18#define NIL (0) // A name for the void pointer
19
20main()
21{
22 // Open the display
23
24 Display *dpy = XOpenDisplay(NIL);
25 assert(dpy);
26
27 // Get some colors
28
29 int blackColor = BlackPixel(dpy, DefaultScreen(dpy));
30 int whiteColor = WhitePixel(dpy, DefaultScreen(dpy));
31
32 // Create the window
33
34 Window w = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0,
35 200, 100, 0, blackColor, blackColor);
36
37 // We want to get MapNotify events
38
39 XSelectInput(dpy, w, StructureNotifyMask);
40
41 // "Map" the window (that is, make it appear on the screen)
42
43 XMapWindow(dpy, w);
44
45 // Create a "Graphics Context"
46
47 GC gc = XCreateGC(dpy, w, 0, NIL);
48
49 // Tell the GC we draw using the white color
50
51 XSetForeground(dpy, gc, whiteColor);
52
53 // Wait for the MapNotify event
54
55 for(;;) {
56 XEvent e;
57 XNextEvent(dpy, &e);
58 if (e.type == MapNotify)
59 break;
60 }
61
62 // Draw the line
63
64 XDrawLine(dpy, w, gc, 10, 60, 180, 20);
65
66 // Send the "DrawLine" request to the server
67
68 XFlush(dpy);
69
70 // Wait for 10 seconds
71
72 sleep(10);
73}
74
diff --git a/xlib-tutorial/server.html b/xlib-tutorial/server.html
deleted file mode 100644
index a408834..0000000
--- a/xlib-tutorial/server.html
+++ /dev/null
@@ -1,89 +0,0 @@
1<HTML>
2<HEAD>
3<TITLE>Xlib programming tutorial: What is all this "client-server" stuff ?</TITLE>
4</HEAD>
5
6<BODY>
7<H1 ALIGN=center>What does all this stuff about "client-server" mean ?</H1>
8
9Everybody says that X has a "client-server" architecture. So this must
10be true, but what does it mean ?
11
12<P>
13
14Well, basically a client-server architecture is conceptually a simple
15thing, but the consequences may be a bit subtle, especially the way it
16is implemented in the Xlib.
17
18<H2>What is a client-server architecture ?</H2>
19
20A client-server architecture is a general mechanism for handling a
21shared resource that several programs may want to access
22simultaneously. In the case of X, the shared resources are the drawing
23area and the input channel. If every process was allowed to write on
24it at its will, several processes may want to draw at the same place,
25resulting in an unpredictable chaos. Thus, only one process is allowed
26to get access to the drawing area: the X server. The processes wanting
27to draw stuff or get inputs send requests to the X servers (they are
28"clients"). They do this over a communication channel. The X server
29performs the requests for its clients, and sends them back replies. It
30may also send messages without explicit client's requests to keep them
31informed of what is going on. These messages sent by the server on its
32own behalf are called "events".
33
34<H2>Advantages of the client-server architecture</H2>
35
36The client-server architecture has several advantages, many of them
37resulting from the ability to run the server and the clients on
38separate machines. Here are some advantages:
39
40<UL>
41
42<LI> A client-server architectured system can be very robust: since
43 the server runs in its own address space, it can protect itself
44 against poorly written clients. Thus, if a client has a bug, it
45 will crash alone, the server and the other clients still running
46 as if nothing has happened.
47
48<LI> The client and the server don't have to run on the same machine,
49 so we have some communication mechanism here.
50
51<LI> The client and the server may run on separate machines, resulting
52 in a better load distribution (possibly).
53
54<LI> The client and the server don't have to run on the same hardware,
55 operating system, etc., giving a better interoperability.
56
57</UL>
58
59<H2>Structure of the X client-server architecture</H2>
60
61As we already mentioned, the server and a client communicates over a
62communication channel. This channel is composed of two layers: the
63low-level one, which is responsible for carrying bytes in a reliable
64way (that is with no loss nor duplication). This link may be among
65others a named pipe in the Unix environment, a DECNet link and of
66course a TCP/IP connection.
67
68<P>
69
70The upper layer use the byte-transport channel to implement a
71higher-level protocol: the X protocol. This protocol says how to tell
72the server to request window creation, graphics drawing, and so on,
73and how the server answers and sends events. The protocol itself is
74separated into different parts:
75
76<UL>
77
78<LI> How to connect and how to break a connection,
79<LI> how to represent the different data types,
80<LI> what are the requests and what they mean and
81<LI> what are the replies and what they mean.
82
83</UL>
84
85[to be continued].
86
87<HR><ADDRESS><A HREF="http://tronche.com/">Christophe Tronche</A>, <A HREF="mailto:ch.tronche@computer.org">ch.tronche@computer.org</A></ADDRESS>
88</BODY>
89</HTML>