summaryrefslogtreecommitdiff
path: root/src/linux
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrikboy@gmail.com>2024-03-08 20:48:05 +0100
committerAldrik Ramaekers <aldrikboy@gmail.com>2024-03-08 20:48:05 +0100
commit0b429e06b8c4b66a9f7fe89b5504315ab4f69616 (patch)
treed5cf9d15d8790559f0c4b006ede0ca1314639077 /src/linux
parentdef620a66bc5b0dc1107102f2c234888dc9bd830 (diff)
linux building
Diffstat (limited to 'src/linux')
-rw-r--r--src/linux/main_linux.cpp296
-rw-r--r--src/linux/mutex.cpp129
2 files changed, 425 insertions, 0 deletions
diff --git a/src/linux/main_linux.cpp b/src/linux/main_linux.cpp
new file mode 100644
index 0000000..f1fc01d
--- /dev/null
+++ b/src/linux/main_linux.cpp
@@ -0,0 +1,296 @@
+#include "imgui.h"
+#include "imgui_spectrum.h"
+#include "imgui_impl_glfw.h"
+#include "imgui_impl_opengl3.h"
+#include "../utf8.h"
+#include "platform.h"
+#include "mutex.h"
+#include "array.h"
+#include "memory_bucket.h"
+#include "image.h"
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#define GL_SILENCE_DEPRECATION
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+#include <GLES2/gl2.h>
+#endif
+#include <GLFW/glfw3.h> // Will drag system OpenGL headers
+
+void ts_create_gui(int window_w, int window_h);
+void ts_load_images();
+void ts_init();
+
+bool program_running = true;
+
+char config_path[MAX_INPUT_LENGTH];
+static const char* _ts_platform_get_config_file_path(char* buffer) {
+ char *env = getenv("HOME");
+ snprintf(buffer, MAX_INPUT_LENGTH, "%s%s", env, "text-search/imgui.ini");
+ return buffer;
+}
+
+static void glfw_error_callback(int error, const char* description)
+{
+ fprintf(stderr, "GLFW Error %d: %s\n", error, description);
+}
+
+// Main code
+int main(int, char**)
+{
+ glfwSetErrorCallback(glfw_error_callback);
+ if (!glfwInit())
+ return 1;
+
+ // Decide GL+GLSL versions
+#if defined(IMGUI_IMPL_OPENGL_ES2)
+ // GL ES 2.0 + GLSL 100
+ const char* glsl_version = "#version 100";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
+#elif defined(__APPLE__)
+ // GL 3.2 + GLSL 150
+ const char* glsl_version = "#version 150";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
+#else
+ // GL 3.0 + GLSL 130
+ const char* glsl_version = "#version 130";
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only
+ //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ only
+#endif
+
+ // Create window with graphics context
+ GLFWwindow* window = glfwCreateWindow(1280, 720, "Text-Search", nullptr, nullptr);
+ if (window == nullptr)
+ return 1;
+ glfwMakeContextCurrent(window);
+ glfwSwapInterval(1); // Enable vsync
+
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+ ImGuiIO& io = ImGui::GetIO(); (void)io;
+ io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
+ io.IniFilename = _ts_platform_get_config_file_path(config_path);
+
+ // Setup Platform/Renderer backends
+ ImGui_ImplGlfw_InitForOpenGL(window, true);
+ ImGui_ImplOpenGL3_Init(glsl_version);
+
+ // Setup Dear ImGui style
+ ImGui::Spectrum::StyleColorsSpectrum();
+ //ImGui::Spectrum::LoadFont(18.0f);
+
+ ts_init();
+ ts_load_images();
+ ts_load_config();
+
+ ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ int display_w, display_h;
+ while (!glfwWindowShouldClose(window))
+ {
+ glfwPollEvents();
+
+ // Start the Dear ImGui frame
+ ImGui_ImplOpenGL3_NewFrame();
+ ImGui_ImplGlfw_NewFrame();
+ ImGui::NewFrame();
+
+ ts_create_gui(display_w, display_h);
+
+ // Rendering
+ ImGui::Render();
+ glfwGetFramebufferSize(window, &display_w, &display_h);
+ glViewport(0, 0, display_w, display_h);
+ glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
+
+ glfwSwapBuffers(window);
+ }
+
+ // Cleanup
+ ImGui_ImplOpenGL3_Shutdown();
+ ImGui_ImplGlfw_Shutdown();
+ ImGui::DestroyContext();
+
+ glfwDestroyWindow(window);
+ glfwTerminate();
+
+ return 0;
+}
+
+bool ts_platform_dir_exists(utf8_int8_t* path) {
+ DIR* dir = opendir(path);
+ if (dir) {
+ /* Directory exists. */
+ closedir(dir);
+ return true;
+ } else if (ENOENT == errno) {
+ return false; // does not exist
+ } else {
+ return false; // error opening dir
+ }
+}
+
+ts_file_content ts_platform_read_file(char *path, const char *mode) {
+ ts_file_content result;
+ result.content = 0;
+ result.content_length = 0;
+ result.file_error = 0;
+
+ FILE *file = fopen(path, mode);
+
+ if (!file)
+ {
+ if (errno == EMFILE)
+ result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_PROCESS;
+ else if (errno == ENFILE)
+ result.file_error = FILE_ERROR_TOO_MANY_OPEN_FILES_SYSTEM;
+ else if (errno == EACCES)
+ result.file_error = FILE_ERROR_NO_ACCESS;
+ else if (errno == EPERM)
+ result.file_error = FILE_ERROR_NO_ACCESS;
+ else if (errno == ENOENT)
+ result.file_error = FILE_ERROR_NOT_FOUND;
+ else if (errno == ECONNABORTED)
+ result.file_error = FILE_ERROR_CONNECTION_ABORTED;
+ else if (errno == ECONNREFUSED)
+ result.file_error = FILE_ERROR_CONNECTION_REFUSED;
+ else if (errno == ENETDOWN)
+ result.file_error = FILE_ERROR_NETWORK_DOWN;
+ else if (errno == EREMOTEIO)
+ result.file_error = FILE_ERROR_REMOTE_IO_ERROR;
+ else if (errno == ESTALE)
+ result.file_error = FILE_ERROR_STALE;
+ else
+ {
+ result.file_error = FILE_ERROR_GENERIC;
+ }
+
+ return result;
+ }
+
+ fseek(file, 0 , SEEK_END);
+ int length = ftell(file);
+ fseek(file, 0, SEEK_SET);
+
+ int length_to_alloc = length+1;
+
+ result.content = malloc(length_to_alloc);
+ if (!result.content) {
+ fclose(file);
+ return result;
+ }
+
+ memset(result.content, 0, length);
+ int read_result = fread(result.content, 1, length, file);
+ if (read_result == 0 && length != 0)
+ {
+ free(result.content);
+ result.content = 0;
+ return result;
+ }
+
+ result.content_length = read_result;
+
+ ((char*)result.content)[length] = 0;
+
+ fclose(file);
+ return result;
+}
+
+void ts_platform_list_files_block(ts_search_result* result, wchar_t* start_dir) {
+
+ utf8_int8_t* search_dir = (utf8_int8_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH);
+ if (start_dir == nullptr) {
+ strcpy(search_dir, result->directory_to_search);
+ }
+ else {
+ strcpy(search_dir, (char*)start_dir);
+ }
+
+ // Append wildcard
+ utf8_int8_t* search_dir_fix = (utf8_int8_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH);
+ strcpy(search_dir_fix, search_dir);
+ strcat(search_dir_fix, u8"/*");
+
+ DIR *d;
+ struct dirent *dir;
+ d = opendir(search_dir);
+ if (d) {
+ chdir(search_dir);
+ while ((dir = readdir(d)) != NULL) {
+ if (result->cancel_search) return;
+ chdir(search_dir);
+
+ if (dir->d_type == DT_DIR)
+ {
+ if ((strcmp(dir->d_name, ".") == 0) || (strcmp(dir->d_name, "..") == 0))
+ continue;
+
+ utf8_int8_t complete_file_path[MAX_INPUT_LENGTH];
+ strcpy(complete_file_path, search_dir);
+ strcat(complete_file_path, "/");
+ strcat(complete_file_path, dir->d_name);
+
+ // do recursive search
+ ts_platform_list_files_block(result, (wchar_t*)complete_file_path);
+ }
+ // we handle DT_UNKNOWN for file systems that do not support type lookup.
+ else if (dir->d_type == DT_REG || dir->d_type == DT_UNKNOWN)
+ {
+ char *matched_filter = 0;
+ if (ts_filter_matches(&result->filters, dir->d_name, &matched_filter) == -1) {
+ continue;
+ }
+ (void)matched_filter;
+
+
+ utf8_int8_t complete_file_path[MAX_INPUT_LENGTH];
+ strcpy(complete_file_path, search_dir);
+ strcat(complete_file_path, "/");
+ strcat(complete_file_path, dir->d_name);
+
+ ts_found_file* f = (ts_found_file*)ts_memory_bucket_reserve(&result->memory, sizeof(ts_found_file));
+ f->path = (utf8_int8_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH);
+ f->match_count = 0;
+ f->error = 0;
+ strcpy(f->path, complete_file_path);
+
+ ts_mutex_lock(&result->files.mutex);
+ ts_array_push_size(&result->files, &f, sizeof(ts_found_file*));
+ ts_mutex_unlock(&result->files.mutex);
+ }
+ }
+ closedir(d);
+ }
+}
+
+uint64_t ts_platform_get_time(uint64_t compare) {
+ struct timespec tms;
+ if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&tms)) {
+ return -1;
+ }
+ long result = 0;
+ result = tms.tv_sec * 1000000;
+ result += tms.tv_nsec/1000;
+ if (tms.tv_nsec % 1000 >= 500) {
+ ++result;
+ }
+
+ if (compare != 0) {
+ return result - compare;
+ }
+
+ return result;
+}
diff --git a/src/linux/mutex.cpp b/src/linux/mutex.cpp
new file mode 100644
index 0000000..f59a1eb
--- /dev/null
+++ b/src/linux/mutex.cpp
@@ -0,0 +1,129 @@
+#include "mutex.h"
+
+extern long int syscall (long int __sysno, ...);
+extern int pthread_tryjoin_np(pthread_t ts_thread, void **retval);
+
+ts_thread ts_thread_start(void *(*start_routine) (void *), void *arg)
+{
+ ts_thread result;
+ result.valid = false;
+
+ pthread_attr_t attr;
+ int attr_init_result = pthread_attr_init(&attr);
+ if (attr_init_result)
+ return result;
+
+ int start_thread_result = pthread_create(&result.thread, &attr, start_routine, arg);
+ if (start_thread_result)
+ {
+ pthread_attr_destroy(&attr);
+ return result;
+ }
+
+ result.valid = true;
+ pthread_attr_destroy(&attr);
+
+ return result;
+}
+
+void ts_thread_detach(ts_thread *ts_thread)
+{
+ if (ts_thread->valid)
+ {
+ pthread_detach(ts_thread->thread);
+ }
+}
+
+void ts_thread_join(ts_thread *ts_thread)
+{
+ if (ts_thread->valid)
+ {
+ void *retval;
+ pthread_join(ts_thread->thread, &retval);
+ }
+}
+
+bool ts_thread_tryjoin(ts_thread *ts_thread)
+{
+ if (ts_thread->valid)
+ {
+ void *retval;
+ bool thread_joined = !pthread_tryjoin_np(ts_thread->thread, &retval);
+ return thread_joined;
+ }
+ return false;
+}
+
+void ts_thread_exit()
+{
+ pthread_exit(0);
+}
+
+void ts_thread_stop(ts_thread *ts_thread)
+{
+ if (ts_thread->valid)
+ {
+ pthread_cancel(ts_thread->thread);
+ }
+}
+
+ts_mutex ts_mutex_create()
+{
+ ts_mutex result;
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
+
+ pthread_mutex_init(&result.mutex, &attr);
+
+ pthread_mutexattr_destroy(&attr);
+
+ return result;
+}
+
+ts_mutex ts_mutex_create_recursive()
+{
+ ts_mutex result;
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init(&result.mutex, &attr);
+
+ pthread_mutexattr_destroy(&attr);
+
+ return result;
+}
+
+void ts_mutex_lock(ts_mutex *ts_mutex)
+{
+ pthread_mutex_lock(&ts_mutex->mutex);
+}
+
+bool ts_mutex_trylock(ts_mutex *ts_mutex)
+{
+ return !pthread_mutex_trylock(&ts_mutex->mutex);
+}
+
+void ts_mutex_unlock(ts_mutex *ts_mutex)
+{
+ pthread_mutex_unlock(&ts_mutex->mutex);
+}
+
+void ts_mutex_destroy(ts_mutex *ts_mutex)
+{
+ ts_mutex_unlock(ts_mutex);
+ pthread_mutex_destroy(&ts_mutex->mutex);
+}
+
+int ts_thread_get_id()
+{
+ return (int)syscall(__NR_gettid);
+}
+
+void ts_thread_sleep(int microseconds)
+{
+ usleep(microseconds);
+} \ No newline at end of file