summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornasr <nsrddyn@gmail.com>2026-01-28 13:13:40 +0100
committernasr <nsrddyn@gmail.com>2026-01-28 13:13:40 +0100
commit3913d1778318cd0c6bfb871148d38abb33ec7fd3 (patch)
tree917728adbf32c877ad591ad9d42f727cc7540b9b
parent7dead79e05e03a71a502ca4e75d05d126ff9f25c (diff)
checkpoint
-rw-r--r--.clangd70
-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.sh35
-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
-rwxr-xr-xmainbin72320 -> 85960 bytes
-rw-r--r--main.c345
-rw-r--r--xlib-tutorial/2nd-program-anatomy.html282
-rw-r--r--xlib-tutorial/Xlib.pdfbin0 -> 357941 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
19 files changed, 1474 insertions, 210 deletions
diff --git a/.clangd b/.clangd
index 1fa5635..759ad19 100644
--- a/.clangd
+++ b/.clangd
@@ -1,39 +1,39 @@
1CompileFlags: 1CompileFlags:
2 Add: 2 # Add:
3 - -std=c99 3 # - -std=c99
4 - -xc 4 # - -xc
5 5 #
6 - -Iinclude 6 # - -Iinclude
7 - -Wall 7 # - -Wall
8 - -Wextra 8 # - -Wextra
9 - -Wpedantic 9 # - -Wpedantic
10 - -Wshadow 10 # - -Wshadow
11 - -Wconversion 11 # - -Wconversion
12 - -Wsign-conversion 12 # - -Wsign-conversion
13 - -Wmissing-declarations 13 # - -Wmissing-declarations
14 - -Wundef 14 # - -Wundef
15 - -Wpointer-arith 15 # - -Wpointer-arith
16 - -Wcast-align 16 # - -Wcast-align
17 - -Wcast-qual 17 # - -Wcast-qual
18 - -Wwrite-strings 18 # - -Wwrite-strings
19 - -Wswitch-enum 19 # - -Wswitch-enum
20 - -Wformat=2 20 # - -Wformat=2
21 - -Wstrict-aliasing=2 21 # - -Wstrict-aliasing=2
22 - -Werror=implicit-function-declaration 22 # - -Werror=implicit-function-declaration
23 - -Werror=implicit-int 23 # - -Werror=implicit-int
24 - -Werror=incompatible-pointer-types 24 # - -Werror=incompatible-pointer-types
25 - -Werror=return-type 25 # - -Werror=return-type
26 - -Wformat-security 26 # - -Wformat-security
27 - -Wnull-dereference 27 # - -Wnull-dereference
28 - -Wmisleading-indentation 28 # - -Wmisleading-indentation
29 29 #
30 - -Wuninitialized 30 # - -Wuninitialized
31 - -Werror 31 # - -Werror
32 - -Wdouble-promotion 32 # - -Wdouble-promotion
33 - -Wstrict-overflow=2 33 # - -Wstrict-overflow=2
34 34 #
35 - -D_POSIX_C_SOURCE=200809L 35 # - -D_POSIX_C_SOURCE=200809L
36 - "-I/include" 36 # - "-I/include"
37 37
38 Remove: 38 Remove:
39 - -std=* 39 - -std=*
diff --git a/base/base.c b/base/base.c
new file mode 100644
index 0000000..ba8ba32
--- /dev/null
+++ b/base/base.c
@@ -0,0 +1,69 @@
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
new file mode 100644
index 0000000..8ce6cba
--- /dev/null
+++ b/base/base.h
@@ -0,0 +1,85 @@
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
new file mode 100644
index 0000000..16997b2
--- /dev/null
+++ b/base/base_arena.c
@@ -0,0 +1,86 @@
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
new file mode 100644
index 0000000..19c4f3d
--- /dev/null
+++ b/base/base_arena.h
@@ -0,0 +1,49 @@
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 578bc8b..80f3d5a 100755
--- a/build.sh
+++ b/build.sh
@@ -1,24 +1,31 @@
1#!/bin/sh 1#!/bin/sh
2set -eu 2set -eu
3 3
4# Toolchain
4CC=clang 5CC=clang
6
7# Files
5SRC=main.c 8SRC=main.c
6OUT=main 9OUT=main
7 10
11# Include paths
12INCLUDES="-I."
13
14# Compiler flags
15CFLAGS="
16-g
17-O0
18"
8 19
9$CC \ 20# Linker flags
10 -Wall -Wextra \ 21LDFLAGS="
11 -v \ 22-lX11
12 "$SRC" \ 23-I.
13 -o "$OUT" \ 24-lm
14 -lX11 \ 25"
15 -lm
16echo
17 26
18echo "== Binary info ==" 27echo "==> Building $OUT"
19file "$OUT" 28$CC $CFLAGS $INCLUDES "$SRC" -o "$OUT" $LDFLAGS
20ldd "$OUT"
21echo
22 29
23echo "== Running ==" 30echo "==> Running $OUT"
24LD_DEBUG=libs ./"$OUT" 31./"$OUT"
diff --git a/library/arena.c b/library/arena.c
new file mode 100644
index 0000000..39711d5
--- /dev/null
+++ b/library/arena.c
@@ -0,0 +1,81 @@
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
new file mode 100644
index 0000000..330023e
--- /dev/null
+++ b/library/arena.h
@@ -0,0 +1,69 @@
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
new file mode 100644
index 0000000..74b6303
--- /dev/null
+++ b/library/base.h
@@ -0,0 +1,42 @@
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
new file mode 100644
index 0000000..3c61d5e
--- /dev/null
+++ b/library/clang-format
@@ -0,0 +1,104 @@
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
new file mode 100644
index 0000000..624678a
--- /dev/null
+++ b/library/clangd
@@ -0,0 +1,59 @@
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 b/main
index 529c2d0..28736dd 100755
--- a/main
+++ b/main
Binary files differ
diff --git a/main.c b/main.c
index 0118363..4c43245 100644
--- a/main.c
+++ b/main.c
@@ -4,231 +4,254 @@
4#include <string.h> 4#include <string.h>
5#include <time.h> 5#include <time.h>
6#include <unistd.h> 6#include <unistd.h>
7#include <stdio.h>
7 8
8#define NIL (0) 9#include "base/base.h"
10#include "base/base_arena.h"
9 11
10#define internal static 12#include "base/base.c"
11#define global static 13#include "base/base_arena.c"
12#define local static
13 14
14typedef uint64_t u64;
15typedef uint32_t u32;
16typedef uint16_t u16;
17typedef uint8_t u8;
18 15
19typedef int8_t i8; 16#define NIL 0
20typedef int16_t i16;
21typedef int32_t i32;
22typedef int64_t i64;
23
24typedef float f32;
25typedef double f64;
26
27typedef i16 b16;
28typedef i32 b32;
29 17
30typedef struct 18typedef struct
31{ 19{
32 i32 x; 20i32 x;
33 i32 y; 21i32 y;
34 u32 height; 22u32 height;
35 u32 width; 23u32 width;
36 u32 border_width; 24u32 border_width;
37 i32 window_depth; 25i32 window_depth;
38 u32 window_class; 26u32 window_class;
39 u64 value_mask; 27u64 value_mask;
40 28
41} WindowProperties; 29} WindowProperties;
42 30
43typedef struct 31typedef struct
44{ 32{
45 i32 x; 33i32 x;
46 i32 y; 34i32 y;
47 i32 z; 35i32 z;
48 36
49} vertex; 37} vertex;
50 38
51void 39void
52sleep_ms(long ms) 40sleep_ms(long ms)
53{ 41{
54 struct timespec ts; 42struct timespec ts;
55 ts.tv_sec = ms / 1000; 43ts.tv_sec = ms / 1000;
56 ts.tv_nsec = (ms % 1000) * 1000000L; 44ts.tv_nsec = (ms % 1000) * 1000000L;
57 45
58 while (nanosleep(&ts, &ts)) 46while (nanosleep(&ts, &ts))
59 { 47{
60 NULL; 48NULL;
61 } 49}
62} 50}
63 51
64void 52void
65move_down(double *y) 53move_down(double *y)
66{ 54{
67 ++*y; 55++*y;
68} 56}
69 57
70void 58void
71move_up(double *y) 59move_up(double *y)
72{ 60{
73 --*y; 61--*y;
62}
63
64void
65move_left(double *x)
66{
67--*x;
68}
69
70void
71move_right(double *x)
72{
73++*x;
74} 74}
75 75
76
77
76typedef struct 78typedef struct
77{ 79{
78 void (*move)(double *a); 80void (*move)(double *a);
79} movement; 81} movement;
80 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
81int 106int
82main() 107main()
83{ 108{
84 Display *MainDisplay = XOpenDisplay(NIL); 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);
85 116
86 Window root = XDefaultRootWindow(MainDisplay); 117XSetWindowAttributes wa = {
87 int screen = DefaultScreen(MainDisplay); 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};
88 134
89 Visual *v = DefaultVisual(MainDisplay, screen); 135i32 dp_heigth = DisplayHeight(MainDisplay, screen);
136i32 dp_width = DisplayWidth(MainDisplay, screen);
90 137
91 XSetWindowAttributes wa = { 138WindowProperties p = {
92 .background_pixmap = None,
93 .background_pixel = BlackPixel(MainDisplay, DefaultScreen(MainDisplay)),
94 .border_pixmap = CopyFromParent,
95 .border_pixel = 0,
96 .bit_gravity = ForgetGravity,
97 .win_gravity = NorthWestGravity,
98 .backing_store = NotUseful,
99 .backing_planes = 1,
100 .backing_pixel = 0,
101 .save_under = False,
102 .event_mask = {},
103 .do_not_propagate_mask = {},
104 .override_redirect = False,
105 .colormap = CopyFromParent,
106 .cursor = None
107 };
108 139
109 i32 dp_heigth = DisplayHeight(MainDisplay, screen); 140.x = dp_width / 2,
110 i32 dp_width = DisplayWidth(MainDisplay, screen); 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,
111 148
112 WindowProperties p = { 149};
113 150
114 .x = dp_width / 2,
115 .y = dp_heigth / 2,
116 .width = (u32)400,
117 .height = (u32)400,
118 .border_width = 0,
119 .window_depth = CopyFromParent,
120 .window_class = CopyFromParent,
121 .value_mask = CWBackPixel,
122 151
123 }; 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);
124 166
125 Window window = 167Pixmap pixmap = XCreatePixmap(MainDisplay, window, dp_width, dp_heigth, 1);
126 XCreateWindow(
127 MainDisplay,
128 root,
129 p.x,
130 p.y,
131 p.width,
132 p.height,
133 p.border_width,
134 p.window_depth,
135 p.window_class,
136 v,
137 p.value_mask,
138 &wa);
139 168
140 XSetWindowBorder(MainDisplay, window, 60); 169XSetWindowBorder(MainDisplay, window, 60);
141 XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask); 170XSelectInput(MainDisplay, window, ExposureMask | StructureNotifyMask);
142 XMapWindow(MainDisplay, window); 171XMapWindow(MainDisplay, window);
143 172
144 double x = p.width / 2;
145 double y = p.height / 2;
146 u32 rect_width = 50;
147 u32 rect_height = 50;
148 173
149 b16 running = 1; 174double x = p.width / 2;
175double y = p.height / 2;
150 176
151 u64 color = 0x0000ff00; 177u32 rect_width = 50;
178u32 rect_height = 50;
152 179
153 GC gc = XCreateGC(MainDisplay, window, 0, NIL); 180u64 color = 0x0000ff00;
154 GC textGc = XCreateGC(MainDisplay, window, 0, NIL);
155 XSetForeground(MainDisplay, gc, color);
156 181
157 double *pX = &x; 182GC gc = XCreateGC(MainDisplay, window, 0, NIL);
158 double *pY = &y; 183XSetForeground(MainDisplay, gc, color);
159 184
160 movement m = {
161 .move = move_down
162 };
163 185
164 while (running) 186double *pX = &x;
165 { 187double *pY = &y;
166 if (*pY + rect_height >= p.height) 188
167 { 189movement m = {
168 m.move = move_up; 190.move = move_down
169 } 191};
170 else if (*pY <= 0) 192
171 { 193XEvent event;
172 m.move = move_down; 194XNextEvent(MainDisplay, &event);
173 } 195
196for (;;)
197{
198switch (event.type)
199case KeyPress:
200case KeyRelease:
201{
202
174 203
175 char words[] = "working"; 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}
176 215
177 XTextItem ti = { 216char words[] = "working";
178 .chars = words,
179 .nchars = (int)strlen(words),
180 .delta = 0,
181 .font = None
182 };
183 217
184 XClearWindow(MainDisplay, window); 218XTextItem ti = {
219.chars = words,
220.nchars = (int)strlen(words),
221.delta = 0,
222.font = None
223};
185 224
186 XDrawText( 225XClearWindow(MainDisplay, window);
187 MainDisplay,
188 window,
189 textGc,
190 50,
191 50,
192 &ti,
193 1);
194 226
195 XFillRectangle( 227pos *p = arena_push(arena, sizeof(*p), 0);
196 MainDisplay,
197 window,
198 gc,
199 (i32)*pX,
200 (i32)*pY,
201 rect_height,
202 rect_width);
203 228
204 XFillRectangle( 229p->z = 10;
205 MainDisplay, 230p->x = ((i32)*pX * 10) / p->z;
206 window, 231p->y = ((i32)*pY * 10) / p->z;
207 gc,
208 (i32)*pX + 100,
209 (i32)*pY,
210 rect_height,
211 rect_width);
212 232
213 XFillRectangle( 233XFillRectangle(
214 MainDisplay, 234MainDisplay,
215 window, 235window,
216 gc, 236gc,
217 (i32)*pX - 100, 237(i32)p->x,
218 (i32)*pY, 238(i32)p->y,
219 rect_height, 239rect_height,
220 rect_width); 240rect_width);
221 241
222 m.move(pY); 242m.move(&x);
223 243
224 sleep_ms(10); 244sleep_ms(1);
225 245
226 XFlush(MainDisplay); 246XFlush(MainDisplay);
227 } 247}
228 248
229 XFreeGC(MainDisplay, gc); 249case DestroyNotify:
230 XFreeGC(MainDisplay, textGc); 250{
231 XCloseDisplay(MainDisplay); 251// handle_destroy(MainDisplay, &gc);
252}
253}
232 254
233 return 0; 255arena_clear(arena);
256return 0;
234} 257}
diff --git a/xlib-tutorial/2nd-program-anatomy.html b/xlib-tutorial/2nd-program-anatomy.html
new file mode 100644
index 0000000..d156f7a
--- /dev/null
+++ b/xlib-tutorial/2nd-program-anatomy.html
@@ -0,0 +1,282 @@
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
new file mode 100644
index 0000000..cef1647
--- /dev/null
+++ b/xlib-tutorial/Xlib.pdf
Binary files differ
diff --git a/xlib-tutorial/index.html b/xlib-tutorial/index.html
new file mode 100644
index 0000000..5e57eaf
--- /dev/null
+++ b/xlib-tutorial/index.html
@@ -0,0 +1,116 @@
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
new file mode 100644
index 0000000..3ba596b
--- /dev/null
+++ b/xlib-tutorial/prog-1.cc
@@ -0,0 +1,29 @@
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
new file mode 100644
index 0000000..51ea0e9
--- /dev/null
+++ b/xlib-tutorial/prog-2.cc
@@ -0,0 +1,74 @@
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
new file mode 100644
index 0000000..a408834
--- /dev/null
+++ b/xlib-tutorial/server.html
@@ -0,0 +1,89 @@
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>