From 0b429e06b8c4b66a9f7fe89b5504315ab4f69616 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Fri, 8 Mar 2024 20:48:05 +0100 Subject: linux building --- src/array.cpp | 3 + src/config.cpp | 8 +- src/image.cpp | 4 +- src/image.h | 14 ++ src/linux/main_linux.cpp | 296 +++++++++++++++++++++++++++++++++ src/linux/mutex.cpp | 129 +++++++++++++++ src/main_windows.cpp | 384 ------------------------------------------- src/memory_bucket.cpp | 1 + src/mutex.cpp | 102 ------------ src/mutex.h | 23 ++- src/platform.h | 1 - src/windows/main_windows.cpp | 384 +++++++++++++++++++++++++++++++++++++++++++ src/windows/mutex.cpp | 102 ++++++++++++ 13 files changed, 956 insertions(+), 495 deletions(-) create mode 100644 src/linux/main_linux.cpp create mode 100644 src/linux/mutex.cpp delete mode 100644 src/main_windows.cpp delete mode 100644 src/mutex.cpp create mode 100644 src/windows/main_windows.cpp create mode 100644 src/windows/mutex.cpp (limited to 'src') diff --git a/src/array.cpp b/src/array.cpp index 38b7095..a0b5863 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -1,5 +1,8 @@ #include "array.h" +#include +#include + ts_array ts_array_create(int entry_size) { ts_array new_ts_array; diff --git a/src/config.cpp b/src/config.cpp index 4813c5c..216c93d 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -3,6 +3,8 @@ #include "search.h" #include +#include +#include utf8_int8_t path_buffer[MAX_INPUT_LENGTH]; utf8_int8_t filter_buffer[MAX_INPUT_LENGTH]; @@ -19,9 +21,9 @@ static void _ts_config_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entr int threads, maxSize; - if (sscanf(line, "Path=%s", &path) == 1) { strcpy_s(path_buffer, MAX_INPUT_LENGTH, (char*)path); } - else if (sscanf(line, "Filter=%s", &filter) == 1) { strcpy_s(filter_buffer, MAX_INPUT_LENGTH, (char*)filter); } - else if (sscanf(line, "Query=%s", &query) == 1) { strcpy_s(query_buffer, MAX_INPUT_LENGTH, (char*)query); } + if (sscanf(line, "Path=%s", &path) == 1) { strcpy(path_buffer, (char*)path); } + else if (sscanf(line, "Filter=%s", &filter) == 1) { strcpy(filter_buffer, (char*)filter); } + else if (sscanf(line, "Query=%s", &query) == 1) { strcpy(query_buffer, (char*)query); } else if (sscanf(line, "Threads=%d", &threads) == 1) { ts_thread_count = threads; } else if (sscanf(line, "MaxSize=%d", &maxSize) == 1) { max_file_size = maxSize; } } diff --git a/src/image.cpp b/src/image.cpp index ba67859..0755055 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -71,8 +71,8 @@ void ts_load_images() { glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); //glGenerateMipmap(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 0); diff --git a/src/image.h b/src/image.h index 21f3438..860c767 100644 --- a/src/image.h +++ b/src/image.h @@ -1,6 +1,7 @@ #ifndef INCLUDE_IMAGE #define INCLUDE_IMAGE +#if defined(_WIN32) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -13,6 +14,19 @@ typedef struct t_ts_image { int width; int height; } ts_image; +#elif defined(__linux__) + +//#include +#include "imgui.h" +#include "imgui_impl_opengl3_loader.h" +#include "imgui_impl_opengl3.h" + +typedef struct t_ts_image { + GLuint id; + int width; + int height; +} ts_image; +#endif extern ts_image img_logo; extern ts_image img_search; 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 +#include +#include +#include +#include +#include +#define GL_SILENCE_DEPRECATION +#if defined(IMGUI_IMPL_OPENGL_ES2) +#include +#endif +#include // 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 diff --git a/src/main_windows.cpp b/src/main_windows.cpp deleted file mode 100644 index 4410f12..0000000 --- a/src/main_windows.cpp +++ /dev/null @@ -1,384 +0,0 @@ -#include - -#include "../imgui/imgui.h" -#include "../imgui/imgui_spectrum.h" -#include "../imgui/imgui_impl_opengl3.h" -#include "../imgui/imgui_impl_win32.h" -#include "../utf8.h" -#include "platform.h" -#include "mutex.h" -#include "array.h" -#include "memory_bucket.h" -#include "image.h" -#include "config.h" -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include -#include -#include -#include - -#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") - -#define IDI_LOGO 123 - -char config_path[MAX_INPUT_LENGTH]; - -void ts_create_gui(int window_w, int window_h); -void ts_load_images(); -void ts_init(); - -struct WGL_WindowData { HDC hDC; }; - -// Data -static HGLRC g_hRC; -static WGL_WindowData g_MainWindow; -static int g_Width; -static int g_Height; -LARGE_INTEGER Frequency; -bool program_running = true; - -bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data); -void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data); -void ResetDeviceWGL(); -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - -static const char* _ts_platform_get_config_file_path(char* buffer) { - if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, buffer))) - { - strcat_s(buffer, MAX_INPUT_LENGTH, "\\text-search\\config.ini"); - return buffer; - } - - return 0; -} - -bool ts_platform_dir_exists(utf8_int8_t* dir) -{ - DWORD ftyp = GetFileAttributesA(dir); - if (ftyp == INVALID_FILE_ATTRIBUTES) - return false; - if (ftyp & FILE_ATTRIBUTE_DIRECTORY) - return true; - return false; -} - -uint64_t ts_platform_get_time(uint64_t compare) -{ - LARGE_INTEGER stamp; - QueryPerformanceCounter(&stamp); - if (compare != 0) { - return (stamp.QuadPart - compare) * 1000 / Frequency.QuadPart; - } - return stamp.QuadPart; -} - -int main(int, char**) -{ - // Create application window - //ImGui_ImplWin32_EnableDpiAwareness(); - WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr }; - ::RegisterClassExW(&wc); - HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Text-Search", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr); - - // Initialize OpenGL - if (!CreateDeviceWGL(hwnd, &g_MainWindow)) - { - CleanupDeviceWGL(hwnd, &g_MainWindow); - ::DestroyWindow(hwnd); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); - return 1; - } - wglMakeCurrent(g_MainWindow.hDC, g_hRC); - - // Show the window - ::ShowWindow(hwnd, SW_SHOWDEFAULT); - ::UpdateWindow(hwnd); - - HICON hicoCaption = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_LOGO)); - SendMessage(hwnd, WM_SETICON, ICON_BIG, - reinterpret_cast(hicoCaption)); - - // Setup Dear ImGui context - 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 Dear ImGui style - ImGui::Spectrum::StyleColorsSpectrum(); - ImGui::Spectrum::LoadFont(18.0f); - //ImGui::StyleColorsLight(); - - // Setup Platform/Renderer backends - ImGui_ImplWin32_InitForOpenGL(hwnd); - ImGui_ImplOpenGL3_Init(); - - QueryPerformanceFrequency(&Frequency); - - ts_init(); - ts_load_images(); - ts_load_config(); - - ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - bool done = false; - while (program_running) - { - MSG msg; - while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) - { - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - if (msg.message == WM_QUIT) - program_running = false; - } - if (!program_running) - break; - - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplWin32_NewFrame(); - ImGui::NewFrame(); - - ts_create_gui(g_Width, g_Height); - - // Rendering - ImGui::Render(); - glViewport(0, 0, g_Width, g_Height); - glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); - glClear(GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - - // Present - ::SwapBuffers(g_MainWindow.hDC); - } - - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplWin32_Shutdown(); - ImGui::DestroyContext(); - - CleanupDeviceWGL(hwnd, &g_MainWindow); - wglDeleteContext(g_hRC); - ::DestroyWindow(hwnd); - ::UnregisterClassW(wc.lpszClassName, wc.hInstance); - - return 0; -} - -bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data) -{ - HDC hDc = ::GetDC(hWnd); - PIXELFORMATDESCRIPTOR pfd = { 0 }; - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 32; - - const int pf = ::ChoosePixelFormat(hDc, &pfd); - if (pf == 0) - return false; - if (::SetPixelFormat(hDc, pf, &pfd) == FALSE) - return false; - ::ReleaseDC(hWnd, hDc); - - data->hDC = ::GetDC(hWnd); - if (!g_hRC) - g_hRC = wglCreateContext(data->hDC); - return true; -} - -void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data) -{ - wglMakeCurrent(nullptr, nullptr); - ::ReleaseDC(hWnd, data->hDC); -} - -extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) - return true; - - switch (msg) - { - case WM_GETMINMAXINFO: - { - MINMAXINFO *minmax = (MINMAXINFO *)lParam; - minmax->ptMinTrackSize.x = 800; - minmax->ptMinTrackSize.y = 600; - break; - } - case WM_SIZE: - if (wParam != SIZE_MINIMIZED) - { - g_Width = LOWORD(lParam); - g_Height = HIWORD(lParam); - } - return 0; - case WM_SYSCOMMAND: - if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu - return 0; - break; - case WM_DESTROY: - ::PostQuitMessage(0); - return 0; - } - return ::DefWindowProcW(hWnd, msg, wParam, lParam); -} - -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; - - // convert utf8 to wchar path. - wchar_t wchar_buffer[MAX_INPUT_LENGTH]; - MultiByteToWideChar(CP_UTF8, 0, path, -1, (wchar_t*)wchar_buffer, MAX_INPUT_LENGTH); - - const size_t cSize = strlen(mode)+1; - wchar_t* wc = new wchar_t[cSize]; - mbstowcs (wc, mode, cSize); - - FILE *file = _wfopen(wchar_buffer, wc); - 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 - { - result.file_error = FILE_ERROR_GENERIC; - printf("ERROR: %d %s\n", errno, path); - } - - goto done_failure; - } - - 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) goto done; - - 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; - - done: - fclose(file); - done_failure: - return result; -} - -void ts_platform_list_files_block(ts_search_result* result, wchar_t* start_dir) -{ - // Utf8 to wchar str - wchar_t* search_dir = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); - if (start_dir == nullptr) { - MultiByteToWideChar(CP_UTF8, 0, result->directory_to_search, -1, search_dir, MAX_INPUT_LENGTH); - } - else { - wcscpy_s(search_dir, MAX_INPUT_LENGTH, start_dir); - } - - // Append wildcard - wchar_t* search_dir_fix = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); - wcscpy_s(search_dir_fix, MAX_INPUT_LENGTH, search_dir); - wcscat_s(search_dir_fix, MAX_INPUT_LENGTH, L"\\*"); - - WIN32_FIND_DATAW file_info; - HANDLE handle = FindFirstFileW(search_dir_fix, &file_info); - - if (handle == INVALID_HANDLE_VALUE) - { - return; - } - - do - { - if (result->cancel_search) return; - - //if (*is_cancelled) break; - const wchar_t *name = (const wchar_t *)file_info.cFileName; - - // symbolic link is not allowed.. - if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) - continue; - - - if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - if ((wcscmp(name, L".") == 0) || (wcscmp(name, L"..") == 0)) - continue; - - wchar_t* subdir_buffer_path = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); - wcscpy_s(subdir_buffer_path, MAX_INPUT_LENGTH, search_dir); - wcscat_s(subdir_buffer_path, MAX_INPUT_LENGTH, L"\\"); - wcscat_s(subdir_buffer_path, MAX_INPUT_LENGTH, name); - ts_platform_list_files_block(result, subdir_buffer_path); - } - else if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || - (file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) - { - char *matched_filter = 0; - utf8_int8_t uni_name[MAX_INPUT_LENGTH]; - WideCharToMultiByte(CP_UTF8,0,name,-1,(LPSTR)uni_name,MAX_INPUT_LENGTH, NULL, NULL); - if (ts_filter_matches(&result->filters, uni_name, &matched_filter) == -1) { - continue; - } - (void)matched_filter; - - wchar_t complete_file_path[MAX_INPUT_LENGTH]; - wcscpy_s(complete_file_path, MAX_INPUT_LENGTH, search_dir); - wcscat_s(complete_file_path, MAX_INPUT_LENGTH, L"\\"); - wcscat_s(complete_file_path, MAX_INPUT_LENGTH, 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; - WideCharToMultiByte(CP_UTF8,0,complete_file_path,-1,(LPSTR)f->path,MAX_INPUT_LENGTH, NULL, NULL); - - ts_mutex_lock(&result->files.mutex); - ts_array_push_size(&result->files, &f, sizeof(ts_found_file*)); - ts_mutex_unlock(&result->files.mutex); - - } - } - while (FindNextFile(handle, (LPWIN32_FIND_DATAW)&file_info) != 0); - - FindClose(handle); -} \ No newline at end of file diff --git a/src/memory_bucket.cpp b/src/memory_bucket.cpp index 0d163d0..1a1e54d 100644 --- a/src/memory_bucket.cpp +++ b/src/memory_bucket.cpp @@ -1,4 +1,5 @@ #include "memory_bucket.h" +#include ts_memory_bucket ts_memory_bucket_init(int bucket_size) { diff --git a/src/mutex.cpp b/src/mutex.cpp deleted file mode 100644 index f224312..0000000 --- a/src/mutex.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "mutex.h" - -ts_mutex ts_mutex_create() -{ - ts_mutex result; - result.mutex = CreateMutex( - NULL, // default security attributes - FALSE, // initially not owned - NULL); // unnamed ts_mutex - - return result; -} - -ts_mutex ts_mutex_create_recursive() -{ - return ts_mutex_create(); -} - -void ts_mutex_lock(ts_mutex *ts_mutex) -{ - WaitForSingleObject( - ts_mutex->mutex, // handle to ts_mutex - INFINITE); // no time-out interval -} - -int ts_mutex_trylock(ts_mutex *ts_mutex) -{ - return WaitForSingleObject(ts_mutex->mutex, 1) == WAIT_OBJECT_0; -} - -void ts_mutex_unlock(ts_mutex *ts_mutex) -{ - ReleaseMutex(ts_mutex->mutex); -} - -void ts_mutex_destroy(ts_mutex *ts_mutex) -{ - CloseHandle(ts_mutex->mutex); -} - - -ts_thread ts_thread_start(void *(*start_routine) (void *), void *arg) -{ - ts_thread result; - result.valid = 0; - - result.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, - arg, 0, NULL); - result.valid = 1; - - return result; -} - -void ts_thread_join(ts_thread *ts_thread) -{ - if (ts_thread->valid) - { - WaitForSingleObject(ts_thread->thread, INFINITE); - CloseHandle(ts_thread->thread); - } -} - -int ts_thread_tryjoin(ts_thread *ts_thread) -{ - if (ts_thread->valid) - { - int result = WaitForSingleObject(ts_thread->thread, 0); - return result == WAIT_OBJECT_0; - } - return 0; -} - -void ts_thread_detach(ts_thread *ts_thread) -{ - if (ts_thread->valid) - { - CloseHandle(ts_thread->thread); - } -} - -void ts_thread_stop(ts_thread *ts_thread) -{ - if (ts_thread->valid) - { - SuspendThread(ts_thread->thread); - } -} - -int ts_thread_get_id() -{ - return GetCurrentThreadId(); -} - -void ts_thread_exit() -{ - ExitThread(0); -} - -void ts_thread_sleep(int microseconds) -{ - Sleep(microseconds/1000); -} \ No newline at end of file diff --git a/src/mutex.h b/src/mutex.h index a745947..8499bcc 100644 --- a/src/mutex.h +++ b/src/mutex.h @@ -1,7 +1,7 @@ #ifndef INCLUDE_MUTEX #define INCLUDE_MUTEX -#ifdef _WIN32 +#if defined(_WIN32) #include #include /* _beginthread, _endthread */ #include @@ -19,11 +19,28 @@ typedef struct t_ts_thread HANDLE thread; int valid; } ts_thread; + +#elif defined(__linux__) +#include +#include +#include +#include + +typedef struct t_ts_thread +{ + pthread_t thread; + bool valid; +} ts_thread; + +typedef struct t_ts_mutex +{ + pthread_mutex_t mutex; +} ts_mutex; #endif ts_thread ts_thread_start(void *(*start_routine) (void *), void *arg); void ts_thread_join(ts_thread *ts_thread); -int ts_thread_tryjoin(ts_thread *ts_thread); +bool ts_thread_tryjoin(ts_thread *ts_thread); void ts_thread_detach(ts_thread *ts_thread); void ts_thread_stop(ts_thread *ts_thread); int ts_thread_get_id(); @@ -33,7 +50,7 @@ void ts_thread_exit(); ts_mutex ts_mutex_create_recursive(); ts_mutex ts_mutex_create(); void ts_mutex_lock(ts_mutex *ts_mutex); -int ts_mutex_trylock(ts_mutex *ts_mutex); +bool ts_mutex_trylock(ts_mutex *ts_mutex); void ts_mutex_unlock(ts_mutex *ts_mutex); void ts_mutex_destroy(ts_mutex *ts_mutex); diff --git a/src/platform.h b/src/platform.h index 7fdc15a..b9a9e9c 100644 --- a/src/platform.h +++ b/src/platform.h @@ -34,7 +34,6 @@ extern bool program_running; bool ts_platform_dir_exists(utf8_int8_t* dir); ts_file_content ts_platform_read_file(char *path, const char *mode); void ts_platform_list_files_block(ts_search_result* result, wchar_t* start_dir = nullptr); -void ts_platform_list_files(ts_search_result* result); uint64_t ts_platform_get_time(uint64_t compare = 0); // if compare is not 0, return difference between timestamp and now, in milliseconds. #endif \ No newline at end of file diff --git a/src/windows/main_windows.cpp b/src/windows/main_windows.cpp new file mode 100644 index 0000000..cb59d9d --- /dev/null +++ b/src/windows/main_windows.cpp @@ -0,0 +1,384 @@ +#include + +#include "imgui.h" +#include "imgui_spectrum.h" +#include "imgui_impl_opengl3.h" +#include "imgui_impl_win32.h" +#include "../utf8.h" +#include "platform.h" +#include "mutex.h" +#include "array.h" +#include "memory_bucket.h" +#include "image.h" +#include "config.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include + +#pragma comment(linker, "/SUBSYSTEM:windows /ENTRY:mainCRTStartup") + +#define IDI_LOGO 123 + +char config_path[MAX_INPUT_LENGTH]; + +void ts_create_gui(int window_w, int window_h); +void ts_load_images(); +void ts_init(); + +struct WGL_WindowData { HDC hDC; }; + +// Data +static HGLRC g_hRC; +static WGL_WindowData g_MainWindow; +static int g_Width; +static int g_Height; +LARGE_INTEGER Frequency; +bool program_running = true; + +bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data); +void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data); +void ResetDeviceWGL(); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); + +static const char* _ts_platform_get_config_file_path(char* buffer) { + if(SUCCEEDED(SHGetFolderPathA(0, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, buffer))) + { + strcat_s(buffer, MAX_INPUT_LENGTH, "\\text-search\\config.ini"); + return buffer; + } + + return 0; +} + +bool ts_platform_dir_exists(utf8_int8_t* dir) +{ + DWORD ftyp = GetFileAttributesA(dir); + if (ftyp == INVALID_FILE_ATTRIBUTES) + return false; + if (ftyp & FILE_ATTRIBUTE_DIRECTORY) + return true; + return false; +} + +uint64_t ts_platform_get_time(uint64_t compare) +{ + LARGE_INTEGER stamp; + QueryPerformanceCounter(&stamp); + if (compare != 0) { + return (stamp.QuadPart - compare) * 1000 / Frequency.QuadPart; + } + return stamp.QuadPart; +} + +int main(int, char**) +{ + // Create application window + //ImGui_ImplWin32_EnableDpiAwareness(); + WNDCLASSEXW wc = { sizeof(wc), CS_OWNDC, WndProc, 0L, 0L, GetModuleHandle(nullptr), nullptr, nullptr, nullptr, nullptr, L"ImGui Example", nullptr }; + ::RegisterClassExW(&wc); + HWND hwnd = ::CreateWindowW(wc.lpszClassName, L"Text-Search", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, nullptr, nullptr, wc.hInstance, nullptr); + + // Initialize OpenGL + if (!CreateDeviceWGL(hwnd, &g_MainWindow)) + { + CleanupDeviceWGL(hwnd, &g_MainWindow); + ::DestroyWindow(hwnd); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + return 1; + } + wglMakeCurrent(g_MainWindow.hDC, g_hRC); + + // Show the window + ::ShowWindow(hwnd, SW_SHOWDEFAULT); + ::UpdateWindow(hwnd); + + HICON hicoCaption = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_LOGO)); + SendMessage(hwnd, WM_SETICON, ICON_BIG, + reinterpret_cast(hicoCaption)); + + // Setup Dear ImGui context + 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 Dear ImGui style + ImGui::Spectrum::StyleColorsSpectrum(); + ImGui::Spectrum::LoadFont(18.0f); + //ImGui::StyleColorsLight(); + + // Setup Platform/Renderer backends + ImGui_ImplWin32_InitForOpenGL(hwnd); + ImGui_ImplOpenGL3_Init(); + + QueryPerformanceFrequency(&Frequency); + + ts_init(); + ts_load_images(); + ts_load_config(); + + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); + bool done = false; + while (program_running) + { + MSG msg; + while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + if (msg.message == WM_QUIT) + program_running = false; + } + if (!program_running) + break; + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplWin32_NewFrame(); + ImGui::NewFrame(); + + ts_create_gui(g_Width, g_Height); + + // Rendering + ImGui::Render(); + glViewport(0, 0, g_Width, g_Height); + glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); + glClear(GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + // Present + ::SwapBuffers(g_MainWindow.hDC); + } + + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplWin32_Shutdown(); + ImGui::DestroyContext(); + + CleanupDeviceWGL(hwnd, &g_MainWindow); + wglDeleteContext(g_hRC); + ::DestroyWindow(hwnd); + ::UnregisterClassW(wc.lpszClassName, wc.hInstance); + + return 0; +} + +bool CreateDeviceWGL(HWND hWnd, WGL_WindowData* data) +{ + HDC hDc = ::GetDC(hWnd); + PIXELFORMATDESCRIPTOR pfd = { 0 }; + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 32; + + const int pf = ::ChoosePixelFormat(hDc, &pfd); + if (pf == 0) + return false; + if (::SetPixelFormat(hDc, pf, &pfd) == FALSE) + return false; + ::ReleaseDC(hWnd, hDc); + + data->hDC = ::GetDC(hWnd); + if (!g_hRC) + g_hRC = wglCreateContext(data->hDC); + return true; +} + +void CleanupDeviceWGL(HWND hWnd, WGL_WindowData* data) +{ + wglMakeCurrent(nullptr, nullptr); + ::ReleaseDC(hWnd, data->hDC); +} + +extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) + return true; + + switch (msg) + { + case WM_GETMINMAXINFO: + { + MINMAXINFO *minmax = (MINMAXINFO *)lParam; + minmax->ptMinTrackSize.x = 800; + minmax->ptMinTrackSize.y = 600; + break; + } + case WM_SIZE: + if (wParam != SIZE_MINIMIZED) + { + g_Width = LOWORD(lParam); + g_Height = HIWORD(lParam); + } + return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; + case WM_DESTROY: + ::PostQuitMessage(0); + return 0; + } + return ::DefWindowProcW(hWnd, msg, wParam, lParam); +} + +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; + + // convert utf8 to wchar path. + wchar_t wchar_buffer[MAX_INPUT_LENGTH]; + MultiByteToWideChar(CP_UTF8, 0, path, -1, (wchar_t*)wchar_buffer, MAX_INPUT_LENGTH); + + const size_t cSize = strlen(mode)+1; + wchar_t* wc = new wchar_t[cSize]; + mbstowcs (wc, mode, cSize); + + FILE *file = _wfopen(wchar_buffer, wc); + 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 + { + result.file_error = FILE_ERROR_GENERIC; + printf("ERROR: %d %s\n", errno, path); + } + + goto done_failure; + } + + 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) goto done; + + 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; + + done: + fclose(file); + done_failure: + return result; +} + +void ts_platform_list_files_block(ts_search_result* result, wchar_t* start_dir) +{ + // Utf8 to wchar str + wchar_t* search_dir = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); + if (start_dir == nullptr) { + MultiByteToWideChar(CP_UTF8, 0, result->directory_to_search, -1, search_dir, MAX_INPUT_LENGTH); + } + else { + wcscpy_s(search_dir, MAX_INPUT_LENGTH, start_dir); + } + + // Append wildcard + wchar_t* search_dir_fix = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); + wcscpy_s(search_dir_fix, MAX_INPUT_LENGTH, search_dir); + wcscat_s(search_dir_fix, MAX_INPUT_LENGTH, L"\\*"); + + WIN32_FIND_DATAW file_info; + HANDLE handle = FindFirstFileW(search_dir_fix, &file_info); + + if (handle == INVALID_HANDLE_VALUE) + { + return; + } + + do + { + if (result->cancel_search) return; + + //if (*is_cancelled) break; + const wchar_t *name = (const wchar_t *)file_info.cFileName; + + // symbolic link is not allowed.. + if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) + continue; + + + if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + if ((wcscmp(name, L".") == 0) || (wcscmp(name, L"..") == 0)) + continue; + + wchar_t* subdir_buffer_path = (wchar_t*)ts_memory_bucket_reserve(&result->memory, MAX_INPUT_LENGTH); + wcscpy_s(subdir_buffer_path, MAX_INPUT_LENGTH, search_dir); + wcscat_s(subdir_buffer_path, MAX_INPUT_LENGTH, L"\\"); + wcscat_s(subdir_buffer_path, MAX_INPUT_LENGTH, name); + ts_platform_list_files_block(result, subdir_buffer_path); + } + else if ((file_info.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) || + (file_info.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)) + { + char *matched_filter = 0; + utf8_int8_t uni_name[MAX_INPUT_LENGTH]; + WideCharToMultiByte(CP_UTF8,0,name,-1,(LPSTR)uni_name,MAX_INPUT_LENGTH, NULL, NULL); + if (ts_filter_matches(&result->filters, uni_name, &matched_filter) == -1) { + continue; + } + (void)matched_filter; + + wchar_t complete_file_path[MAX_INPUT_LENGTH]; + wcscpy_s(complete_file_path, MAX_INPUT_LENGTH, search_dir); + wcscat_s(complete_file_path, MAX_INPUT_LENGTH, L"\\"); + wcscat_s(complete_file_path, MAX_INPUT_LENGTH, 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; + WideCharToMultiByte(CP_UTF8,0,complete_file_path,-1,(LPSTR)f->path,MAX_INPUT_LENGTH, NULL, NULL); + + ts_mutex_lock(&result->files.mutex); + ts_array_push_size(&result->files, &f, sizeof(ts_found_file*)); + ts_mutex_unlock(&result->files.mutex); + + } + } + while (FindNextFile(handle, (LPWIN32_FIND_DATAW)&file_info) != 0); + + FindClose(handle); +} \ No newline at end of file diff --git a/src/windows/mutex.cpp b/src/windows/mutex.cpp new file mode 100644 index 0000000..47663cd --- /dev/null +++ b/src/windows/mutex.cpp @@ -0,0 +1,102 @@ +#include "mutex.h" + +ts_mutex ts_mutex_create() +{ + ts_mutex result; + result.mutex = CreateMutex( + NULL, // default security attributes + FALSE, // initially not owned + NULL); // unnamed ts_mutex + + return result; +} + +ts_mutex ts_mutex_create_recursive() +{ + return ts_mutex_create(); +} + +void ts_mutex_lock(ts_mutex *ts_mutex) +{ + WaitForSingleObject( + ts_mutex->mutex, // handle to ts_mutex + INFINITE); // no time-out interval +} + +bool ts_mutex_trylock(ts_mutex *ts_mutex) +{ + return WaitForSingleObject(ts_mutex->mutex, 1) == WAIT_OBJECT_0; +} + +void ts_mutex_unlock(ts_mutex *ts_mutex) +{ + ReleaseMutex(ts_mutex->mutex); +} + +void ts_mutex_destroy(ts_mutex *ts_mutex) +{ + CloseHandle(ts_mutex->mutex); +} + + +ts_thread ts_thread_start(void *(*start_routine) (void *), void *arg) +{ + ts_thread result; + result.valid = 0; + + result.thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, + arg, 0, NULL); + result.valid = 1; + + return result; +} + +void ts_thread_join(ts_thread *ts_thread) +{ + if (ts_thread->valid) + { + WaitForSingleObject(ts_thread->thread, INFINITE); + CloseHandle(ts_thread->thread); + } +} + +bool ts_thread_tryjoin(ts_thread *ts_thread) +{ + if (ts_thread->valid) + { + int result = WaitForSingleObject(ts_thread->thread, 0); + return result == WAIT_OBJECT_0; + } + return 0; +} + +void ts_thread_detach(ts_thread *ts_thread) +{ + if (ts_thread->valid) + { + CloseHandle(ts_thread->thread); + } +} + +void ts_thread_stop(ts_thread *ts_thread) +{ + if (ts_thread->valid) + { + SuspendThread(ts_thread->thread); + } +} + +int ts_thread_get_id() +{ + return GetCurrentThreadId(); +} + +void ts_thread_exit() +{ + ExitThread(0); +} + +void ts_thread_sleep(int microseconds) +{ + Sleep(microseconds/1000); +} \ No newline at end of file -- cgit v1.2.3-70-g09d2