client/main.c

changeset 942
488178e3e328
child 944
cc23aad6335e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/main.c	Sun Nov 30 18:15:46 2025 +0100
@@ -0,0 +1,204 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <ui/ui.h>
+#include <cx/printf.h>
+#include <pthread.h>
+
+#include "main.h"
+#include "uiclient.h"
+
+/*
+ * debug window that is always created
+ */
+static UiObject *debug_window;
+
+/*
+ * test window, that is only created in testing mode
+ */
+static UiObject *test_window;
+
+static int test_mode = 0;
+
+static int input_fd[2];
+static int output_fd[2];
+
+int main(int argc, char **argv) {
+    test_mode = 1;
+    
+    ui_init(NULL, argc, argv);
+    ui_onstartup(application_onstartup, NULL);
+    ui_onopen(application_onopen, NULL);
+    ui_onexit(application_onexit, NULL);
+    
+    int in = STDIN_FILENO;
+    int out = STDOUT_FILENO;
+    if(test_mode) {
+        if(pipe(input_fd)) {
+            perror("pipe");
+            return 1;
+        }
+        if(pipe(output_fd)) {
+            perror("pipe");
+            return 1;
+        }
+        
+        in = input_fd[0];
+        out = output_fd[1];
+        
+        pthread_t tid;
+        if(pthread_create(&tid, NULL, testwindow_read_thread, NULL)) {
+            perror("pthread_create");
+            return 1;
+        }
+        if(pthread_detach(tid)) {
+            perror("pthread_detach");
+            return 1;
+        }
+    }
+    MessageHandler *h = simple_msg_handler(in, out, client_msg_received);
+    client_init(h);
+    h->start(h);
+    
+    ui_main();
+    
+    h->stop(h);
+    fprintf(stderr, "client: end");
+    
+    return 0;
+}
+
+void application_onstartup(UiEvent *event, void *userdata) {
+    // We need at least one window for the event loop to work.
+    // Create a debug window, that is invisible by default
+    debug_window = ui_simple_window("debug", NULL);
+    // TODO: debug UI
+    
+    if(test_mode) {
+        testwindow_create();
+    }
+}
+
+void application_onopen(UiEvent *event, void *userdata) {
+    
+}
+
+void application_onexit(UiEvent *event, void *userdata) {
+    
+}
+
+static void testwindow_close(UiEvent *event, void *userdata) {
+    ui_close(debug_window);
+    ui_app_quit();
+    exit(0);
+}
+
+static void testwindow_send(UiEvent *event, void *userdata) {
+    TestWindow *window = event->window;
+    
+    char *str = ui_get(window->input);
+    int len = strlen(str);
+    cxmutstr msg = cx_asprintf("%d\n%s", len, str);
+    write(input_fd[1], msg.ptr, msg.length);
+    free(msg.ptr);
+    
+    ui_set(window->input, "");
+}
+
+static void testwindow_clear_output(UiEvent *event, void *userdata) {
+    TestWindow *window = event->window;
+    ui_set(window->output, "");
+}
+
+void testwindow_create(void) {
+    UiObject *obj = ui_simple_window("Test", NULL);
+    ui_context_closefunc(obj->ctx, testwindow_close, NULL);
+    ui_window_size(obj, 1800, 1400);
+    
+    TestWindow *window = ui_malloc(obj->ctx, sizeof(TestWindow));
+    window->input = ui_text_new(obj->ctx, NULL);
+    window->output = ui_text_new(obj->ctx, NULL);
+    obj->window = window;
+    
+    ui_hsplitpane(obj, .fill = TRUE, .initial_position = 900) {
+        // left
+        ui_vbox(obj, .fill = TRUE) {
+            ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10, .fill = TRUE) {
+                ui_llabel(obj, .label = "Input", .style = UI_LABEL_STYLE_TITLE, .hexpand = TRUE, .hfill = TRUE);
+                ui_newline(obj);
+                ui_textarea(obj, .value = window->input, .fill = TRUE);
+                ui_newline(obj);
+                ui_button(obj, .label = "Send", .onclick = testwindow_send);
+            }
+        }
+        
+        
+        // right
+        ui_vbox(obj, .fill = TRUE) {
+            ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10, .fill = TRUE) {
+                ui_llabel(obj, .label = "Output", .style = UI_LABEL_STYLE_TITLE, .hexpand = TRUE, .hfill = TRUE);
+                ui_newline(obj);
+                ui_textarea(obj, .value = window->output, .fill = TRUE);
+                ui_newline(obj);
+                ui_button(obj, .label = "Clear", .onclick = testwindow_clear_output);
+            }
+        }
+    }
+    
+    ui_show(obj);
+    
+    test_window = obj;
+}
+
+static int append_log(void *data) {
+    char *msg = data;
+    TestWindow *window = test_window->window;
+    UiText *out = window->output;
+    int length = out->length(out);
+    out->insert(out, length, msg);
+    free(msg);
+    return 0;
+}
+
+void* testwindow_read_thread(void *data) {
+    char buf[4096];
+    ssize_t r;
+    while((r = read(output_fd[0], buf, 4096)) > 0) {
+        char *str = malloc(r+1);
+        memcpy(str, buf, r);
+        str[r] = 0;
+        ui_call_mainthread(append_log, str);
+    }
+    
+    return NULL;
+}

mercurial