yterm

commit db44180711f8773fd9fb5394ebfb8a3e1f6f3c68

Author: mesyeti <mesyeti@mesyeti.uk>

add config

 .gitmodules | 3 +
 README.md | 3 +
 docs/config.md | 15 ++++++
 example_config.ini | 3 +
 install_default.sh | 3 +
 source/app.c | 2 
 source/config.c | 101 ++++++++++++++++++++++++++++++++++++++++++++
 source/config.h | 6 ++
 source/platform.h | 3 +
 source/platform/unix.c | 59 +++++++++++++++++++++++++
 source/screen.c | 21 +++++---
 source/screen.h | 1 
 source/util.c | 27 +++++++++++
 source/util.h | 1 


diff --git a/.gitmodules b/.gitmodules
index 431d35d81572daa170007f517078c1565db1310b..3853cc6df8de381a1486906db6482136dc58caab 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
 [submodule "lib/stb"]
 	path = lib/stb
 	url = https://github.com/nothings/stb
+[submodule "lib/tini"]
+	path = lib/tini
+	url = https://codeberg.org/lordoftrident/tini/




diff --git a/README.md b/README.md
index afb592f0915b87928af8bcf67b485769d63066fa..30014cebbb3e08efb54c1a0fa9a5dc489bbce6c9 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,6 @@ make
 ```
 
 Currently requires SDL2, it will switch to libx11 in the near future
+
+## Docs
+See the `docs` folder for documentation




diff --git a/docs/config.md b/docs/config.md
new file mode 100644
index 0000000000000000000000000000000000000000..bae90fe6c0f1c2b584749cd0135f05231112fd60
--- /dev/null
+++ b/docs/config.md
@@ -0,0 +1,15 @@
+# Config
+Config is done via the `config.ini` file in `~/.config/yterm`
+
+Use the `install_default.sh` script to install the default config.
+
+See `example_config.ini` if you want an example.
+
+## Font section (`[font]`)
+### `type`
+Sets what type the font will use. Currently only accepts `bitmap`. Must be used before
+defining which font will be used
+
+### `file`
+Used to select which bitmap font is used. This points to a file in the `~/.config/yterm`
+folder.




diff --git a/example_config.ini b/example_config.ini
new file mode 100644
index 0000000000000000000000000000000000000000..99a54b1122c6f2a79e744402a9ca2a952f40526f
--- /dev/null
+++ b/example_config.ini
@@ -0,0 +1,3 @@
+[font]
+type = bitmap
+file = default_7x16.png




diff --git a/install_default.sh b/install_default.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6c0f33a025b2f2184816b41ae8b4fe4d7a56e0df
--- /dev/null
+++ b/install_default.sh
@@ -0,0 +1,3 @@
+mkdir -p ~/.config/yterm
+cp assets/default_7x16.png ~/.config/yterm/
+cp example_config.ini ~/.config/yterm/








diff --git a/source/app.c b/source/app.c
index 4f0eb5a3e58aa00e57f1c37336dd63f0ca724299..57662e3b083240ba3aa48ddf66256779db42e948 100644
--- a/source/app.c
+++ b/source/app.c
@@ -4,6 +4,7 @@ #include "log.h"
 #include "mem.h"
 #include "event.h"
 #include "screen.h"
+#include "config.h"
 #include "backend.h"
 
 App app;
@@ -14,6 +15,7 @@
 	Event_Init();
 	Window_Init();
 	Video_Init("yterm");
+	Config_Load();
 	Screen_Init();
 
 	bool success;




diff --git a/source/config.c b/source/config.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee5a859c5d1bc6a3e91565a7d94912627fab7f5b
--- /dev/null
+++ b/source/config.c
@@ -0,0 +1,101 @@
+#include "util.h"
+#include "config.h"
+#include "screen.h"
+#include "platform.h"
+
+#define TINI_MULTILINE
+#define TINI_INLINECOMMENTS
+#define TINI_IMPLEMENTATION
+#include <tini/tini.h>
+
+enum {
+	CONF_FONT_NONE,
+	CONF_FONT_BM,
+	CONF_FONT_TTF
+};
+
+static int fontState;
+
+static const char* Callback(char* sect, char* key, char* val, void* data) {
+	(void) data;
+
+	if (strcmp(sect, "font") == 0) {
+		if (strcmp(key, "type") == 0) {
+			if (fontState != CONF_FONT_NONE) {
+				return "Font type already set";
+			}
+
+			if (strcmp(val, "bitmap") == 0) {
+				fontState = CONF_FONT_BM;
+			}
+			else if (strcmp(val, "ttf") == 0) {
+				return "Font type currently not supported";
+			}
+			else {
+				return "Unknown font type";
+			}
+		}
+		else if (strcmp(key, "file") == 0) {
+			if (fontState != CONF_FONT_BM) {
+				return "File property only usable for bitmap fonts";
+			}
+
+			if (screen.fontLoaded) {
+				Font_Free(&screen.font);
+			}
+
+			char* folder = Platform_GetConfigPath();
+
+			char path[1024];
+			strncpy(path, folder, 256);
+			strncat(path, val, 256);
+
+			Log("Loading font '%s'", path);
+
+			bool   success;
+			BMFont font = BMFont_Load(path, &success);
+
+			if (!success) {
+				Error("Failed to load font: %s", val);
+			}
+
+			free(folder);
+			screen.font       = Font_FromBMFont(font);
+			screen.fontLoaded = true;
+		}
+		else {
+			return "Invalid key";
+		}
+	}
+	else {
+		return "Invalid section";
+	}
+
+	return NULL;
+}
+
+void Config_Load(void) {
+	fontState = CONF_FONT_NONE;
+
+	char* folder = Platform_GetConfigPath();
+
+	char path[4096];
+	strncpy(path, folder, 256);
+	strcat(path, "config.ini");
+
+	if (!FileExists(path)) {
+		FILE* file = fopen(path, "w");
+		fprintf(file, "\n");
+		fclose(file);
+	}
+
+	int errorLine;
+
+	const char* error = tiniParsePath(path, &Callback, &errorLine, NULL);
+
+	if (error) {
+		Error("Error on config line %d: %s", errorLine, error);
+	}
+
+	Log("Loaded config");
+}




diff --git a/source/config.h b/source/config.h
new file mode 100644
index 0000000000000000000000000000000000000000..c70792217781a9c9c4b6b880f9f5231dfce57e90
--- /dev/null
+++ b/source/config.h
@@ -0,0 +1,6 @@
+#ifndef YT_CONFIG_H
+#define YT_CONFIG_H
+
+void Config_Load(void);
+
+#endif




diff --git a/source/platform/unix.c b/source/platform/unix.c
index 0aebddacddcfbf87717fc98f0f4b2f6036917ebe..f1f4aeb1f42516cfa195c38bf4d301838fffea44 100644
--- a/source/platform/unix.c
+++ b/source/platform/unix.c
@@ -1,7 +1,14 @@
+#include <string.h>
+#include "../util.h"
 #include "../platform.h"
 
 #if defined(PLATFORM_UNIX) || defined(PLATFORM_LINUX)
+#include <pwd.h>
 #include <time.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 void Platform_Init(void) {
 	
@@ -15,6 +22,58 @@ uint64_t Platform_GetTime(void) {
 	struct timespec time;
 	clock_gettime(CLOCK_MONOTONIC, &time);
 	return time.tv_sec * 1000000 + time.tv_nsec / 1000;
+}
+
+bool Platform_FolderExists(const char* path) {
+	DIR* dir = opendir(path);
+
+	if (dir) {
+		closedir(dir);
+		return true;
+	}
+
+	return false;
+}
+
+void Platform_MakeFolder(const char* path) {
+	mkdir(path, 0700);
+}
+
+char* Platform_GetConfigPath(void) {
+	static bool checked = false;
+
+	char path[1024];
+
+	struct passwd* pw = getpwuid(getuid());
+
+	strncpy(path, pw->pw_dir, 256);
+	strcat(path, "/.config");
+
+	if (!checked && !Platform_FolderExists(path)) {
+		Platform_MakeFolder(path);
+	}
+
+	strcat(path, "/yterm");
+
+	if (!checked && !Platform_FolderExists(path)) {
+		Platform_MakeFolder(path);
+	}
+
+	strcat(path, "/");
+	char* end = &path[strlen(path)];
+
+	if (!checked) {
+		strcat(path, "themes");
+
+		if (!Platform_FolderExists(path)) {
+			Platform_MakeFolder(path);
+		}
+
+		*end = 0;
+	}
+
+	checked = true;
+	return NewString(path);
 }
 
 #endif




diff --git a/source/platform.h b/source/platform.h
index 27962be4902bfb840b45aa65c2675e3891344f1a..202e80600675c2462e0abfc3fcd4e53bc4aa010e 100644
--- a/source/platform.h
+++ b/source/platform.h
@@ -6,5 +6,8 @@
 void     Platform_Init(void);
 void     Platform_Quit(void);
 uint64_t Platform_GetTime(void);
+bool     Platform_FolderExists(const char* path);
+void     Platform_MakeFolder(const char* path);
+char*    Platform_GetConfigPath(void);
 
 #endif




diff --git a/source/screen.c b/source/screen.c
index e060db10f102b21d66ea798e5bbfd94aec3ffc33..e97a9eedde87f5b3c45f202c88e3eef291bd64e4 100644
--- a/source/screen.c
+++ b/source/screen.c
@@ -4,21 +4,26 @@ #include "theme.h"
 #include "screen.h"
 #include "bitmapFont.h"
 
-Screen screen;
+Screen screen = {
+	.fontLoaded = false
+};
 
 void Screen_Init(void) {
 	Theme_Init();
 
 	// load font
-	bool   success;
-	BMFont font = BMFont_Load("assets/default_7x16.png", &success);
+	if (!screen.fontLoaded) {
+		bool   success;
+		BMFont font = BMFont_Load("assets/default_7x16.png", &success);
+
+		if (!success) {
+			Error("Failed to load font");
+			return;
+		}
 
-	if (!success) {
-		Error("Failed to load font");
-		return;
+		screen.font       = Font_FromBMFont(font);
+		screen.fontLoaded = true;
 	}
-
-	screen.font = Font_FromBMFont(font);
 
 	int cw;
 	int ch;




diff --git a/source/screen.h b/source/screen.h
index 8b4ea2faf4e400bceb000200458df0ef810124a2..b7009328396e787682c049bc5628e16c6735c26c 100644
--- a/source/screen.h
+++ b/source/screen.h
@@ -8,6 +8,7 @@ typedef struct {
 	Buffer old;
 	Buffer buffer;
 	Font   font;
+	bool   fontLoaded;
 } Screen;
 
 extern Screen screen;




diff --git a/source/util.c b/source/util.c
index d8d941ce49723bc2e16e5ff223bdb977b1c38713..9a7569e9ed8565638810c85687c6c2448791d652 100644
--- a/source/util.c
+++ b/source/util.c
@@ -7,6 +7,17 @@ #include "util.h"
 #include "video.h"
 #include "common.h"
 
+bool FileExists(const char* path) {
+	FILE* file = fopen(path, "r");
+
+	if (!file) {
+		return false;
+	}
+
+	fclose(file);
+	return true;
+}
+
 float RadToDeg(float rad) {
 	return rad * 180 / PI;
 }
@@ -216,6 +227,22 @@ 			char str2[2] = {str[i], 0};
 			thisString   = ConcatString(thisString, str2);
 		}
 	}
+
+	return ret;
+}
+
+char* ReadFile(const char* str) {
+	FILE* file = fopen(str, "r");
+
+	if (!file) return NULL;
+
+	fseek(file, SEEK_END, 0);
+	size_t size = (size_t) ftell(file);
+	fseek(file, SEEK_SET, 0);
+
+	char* ret = SafeMalloc(size);
+
+	fread(ret, 1, size, file);
 
 	return ret;
 }




diff --git a/source/util.h b/source/util.h
index 2e8ea3ce28922ad27da367de37f8c150e9fd9c3d..285afc5848252ad4b53efa0f5131be14bf6a9fa5 100644
--- a/source/util.h
+++ b/source/util.h
@@ -44,6 +44,7 @@ size_t StrArrayFind(char** array, char* string);
 void   FreeStrArray(char** array);
 bool   StringStartsWith(char* str, char* with);
 char** Split(const char* str, size_t* length, char ch);
+char*  ReadFile(const char* str);
 
 const char* BaseName(const char* path);