diff --git a/Makefile b/Makefile index c6b9d46..544d19a 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ CC := gcc CFLAGS := -g -Wall -Wextra -Werror -pedantic -fno-omit-frame-pointer DEPFLAGS = -MMD -MP +CI2_GUI ?= 0 # Directory Variables LIBDIR := lib @@ -21,7 +22,13 @@ ifeq ($(OS), Windows_NT) PLATFORM_SRCS := $(wildcard $(SRC)/win32_*.c) PLATFORM_OBJS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(PLATFORM_SRCS)) PLATFORM_FLAGS := -D WIN32 -DUNICODE -D_UNICODE - PLATFORM_LIBS := -mwindows + PLATFORM_LIBS := + +ifeq ($(CI2_GUI),1) + PLATFORM_LIBS += -mwindows + PLATFORM_FLAGS += -DCI2_GUI +endif + else UNAME_S := $(shell uname -s) ifeq ($(UNAME_S), Linux) @@ -29,7 +36,13 @@ else PLATFORM_SRCS := $(wildcard $(SRC)/linux_*.c) PLATFORM_OBJS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o, $(PLATFORM_SRCS)) PLATFORM_FLAGS := -D LINUX - PLATFORM_LIBS := -lX11 + PLATFORM_LIBS := +ifeq ($(CI2_GUI),1) + + PLATFORM_FLAGS += -DCI2_GUI + PLATFORM_LIBS += -lX11 +endif + else ifeq ($(UNAME_S), Darwin) PLATFORM := mac PLATFORM_SRCS := $(wildcard $(SRC)/mac_*.c) diff --git a/include/base/ci2_macros.h b/include/base/ci2_macros.h index 068251e..9a62c91 100644 --- a/include/base/ci2_macros.h +++ b/include/base/ci2_macros.h @@ -23,7 +23,6 @@ SOFTWARE. #ifndef CI2_MACROS_H #define CI2_MACROS_H -#define CI2_GUI 1 // -mwindows flag is in makefile #define UNUSED(x) (void)(x) typedef int ci2_bool; diff --git a/include/ci2.h b/include/ci2.h index f0d09f9..39628b0 100644 --- a/include/ci2.h +++ b/include/ci2.h @@ -27,5 +27,25 @@ SOFTWARE. #include "ci2_exception.h" #include "ci2_mem.h" +#ifdef CI2_WINDOWS + #ifdef CI2_GUI + extern int WINAPI ci2_wgui( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow); + #else + #include + #include + extern int WINAPI ci2_wcli(int argc, ci2_sys_char *wargv[]); + #endif // CI2_GUI + +#else // NOT CI2_WINDOWS + extern int ci2_gui( int argc, ci2_sys_char *argv[]); + extern int ci2_cli( int argc, ci2_sys_char *argv[]); +#endif + + + #endif // ci2.h diff --git a/include/ci2_window.h b/include/ci2_window.h index 52e11ce..88b15a6 100644 --- a/include/ci2_window.h +++ b/include/ci2_window.h @@ -50,8 +50,5 @@ void ci2_destroy_window(CI2_Window* window); // Shuts down the ci2 layer void ci2_shutdown(void); -// Non GUI Main -ci2_bool ci2_main(int argc, ci2_sys_char *argv[]); - #endif // ci2_window.h diff --git a/src/linux_ci2.c b/src/linux_ci2.c new file mode 100644 index 0000000..70c9235 --- /dev/null +++ b/src/linux_ci2.c @@ -0,0 +1,41 @@ +/* - | Copyright | -------------------------------------------------------------- + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#include "../include/ci2.h" +#include + +int ci2_gui(int argc, ci2_sys_char *argv[]){ + printf("GUI\n"); + UNUSED(argc); + UNUSED(argv); + return EXIT_SUCCESS; +} + +int ci2_cli(int argc, ci2_sys_char *argv[]){ + printf("CLI\n"); +#ifdef CI2_GUI + printf("\n\nERROR\n\n"); +#endif + UNUSED(argc); + UNUSED(argv); + return EXIT_SUCCESS; +} diff --git a/src/linux_ci2_window.c b/src/linux_ci2_window.c index 81c66ae..a755172 100644 --- a/src/linux_ci2_window.c +++ b/src/linux_ci2_window.c @@ -112,9 +112,3 @@ void ci2_shutdown(void) // Nothing global needed } -ci2_bool ci2_main(int argc, ci2_sys_char *argv[]) -{ - UNUSED(argc); - UNUSED(argv); - return EXIT_SUCCESS; -} diff --git a/src/win32_ci2.c b/src/win32_ci2.c new file mode 100644 index 0000000..8ad72f6 --- /dev/null +++ b/src/win32_ci2.c @@ -0,0 +1,92 @@ +/* - | Copyright | -------------------------------------------------------------- + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#include "../include/ci2.h" + +int WINAPI ci2_wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) { + // Create a console so stdout/stderr work + if (AllocConsole()) { + FILE *f; + freopen_s(&f, "CONOUT$", "w", stdout); + freopen_s(&f, "CONOUT$", "w", stderr); + wprintf(L"Allocated console\n"); + } + WNDCLASSEXW wc = {0}; + wc.cbSize = sizeof(wc); + wc.lpfnWndProc = WndProc; + wc.hInstance = hInstance; + wc.lpszClassName = CLASS_NAME; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + + if (!RegisterClassExW(&wc)) return 0; + + HWND hwnd = CreateWindowExW( + 0, + CLASS_NAME, + L"My -mwindows App", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, + NULL, NULL, hInstance, NULL + ); + + if (!hwnd) return 0; + + ShowWindow(hwnd, nCmdShow); + UpdateWindow(hwnd); + + MSG msg; + while (GetMessageW(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + + return (int)msg.wParam; +} + +int WINAPI ci2_wmain(int argc, wchar_t **argv) { + // You already have a console because this is a console subsystem binary. + wprintf(L"Console present. argc=%d\n", argc); + + HINSTANCE hInst = GetModuleHandleW(NULL); + WNDCLASSW wc = {0}; + wc.lpfnWndProc = WndProc; + wc.hInstance = hInst; + wc.lpszClassName = L"MyWinClass"; + RegisterClassW(&wc); + + HWND hwnd = CreateWindowExW( + 0, wc.lpszClassName, L"GUI from wmain", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + NULL, NULL, hInst, NULL); + ShowWindow(hwnd, SW_SHOW); + + MSG msg; + while (GetMessageW(&msg, NULL, 0, 0)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + wprintf(L"Message loop ended, exit code=%d\n", (int)msg.wParam); + return (int)msg.wParam; +} + + diff --git a/src/win32_ci2_window.c b/src/win32_ci2_window.c index 3d05a7e..6d82331 100644 --- a/src/win32_ci2_window.c +++ b/src/win32_ci2_window.c @@ -112,13 +112,6 @@ void ci2_shutdown(void) // Nothing to do } -ci2_bool ci2_main(int argc, ci2_sys_char *argv[]) -{ - UNUSED(argc); - UNUSED(argv); - return EXIT_SUCCESS; -} - static LRESULT CALLBACK window_proc( HWND hwnd, UINT uMsg, diff --git a/tests/01_main.c b/tests/01_main.c new file mode 100644 index 0000000..07c62be --- /dev/null +++ b/tests/01_main.c @@ -0,0 +1,56 @@ +/* - | Copyright | -------------------------------------------------------------- + Copyright (c) 2026 Randy Jordan + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + * --------------------------------------------------------------------------*/ +#define DEBUG +#include "../include/ci2.h" + +#ifdef CI2_WINDOWS + #ifdef CI2_GUI + int WINAPI WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) + { + return ci2_wgui(hInstance, hPrevInstance, lpCmdLine,nCmdShow); + } + #else + #include + #include + int wmain(int argc, ci2_sys_char *wargv[]) + { + return ci2_wcli(argc, wargv); + } + #endif // CI2_GUI + +#else // NOT CI2_WINDOWS + #ifdef CI2_GUI + int main(int argc, ci2_sys_char *argv[]){ + return ci2_gui(argc, argv); + } + #else + int main(int argc, ci2_sys_char *argv[]){ + return ci2_cli(argc,argv); + } + #endif + +#endif