gs_ddt.h

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

gs_ddt.h (5914B)


      1 #ifndef GS_DDT_H_
      2 #define GS_DDT_H_
      3 
      4 typedef void(*gs_ddt_func)(int argc, char** argv);
      5 
      6 typedef struct gs_ddt_command_s {
      7         gs_ddt_func func;
      8         const char* name;
      9         const char* desc;
     10 } gs_ddt_command_t;
     11 
     12 typedef struct gs_ddt_s {
     13         char tb[2048]; // text buffer
     14         char cb[524]; // "command" buffer
     15 
     16         float y;
     17         float size;
     18         float open_speed;
     19         float close_speed;
     20 
     21         int open;
     22         int last_open_state;
     23         int close_complete;
     24         int autoscroll;
     25 
     26         gs_ddt_command_t* commands;
     27         int commands_len;
     28 } gs_ddt_t;
     29 
     30 extern void gs_ddt_printf(gs_ddt_t* ddt, const char* fmt, ...);
     31 extern void gs_ddt(gs_ddt_t* ddt, gs_gui_context_t* ctx, gs_gui_rect_t screen, const gs_gui_selector_desc_t* desc);
     32 // A gui context must be begun before this is ran
     33 
     34 #ifdef GS_DDT_IMPL
     35 
     36 void
     37 gs_ddt_printf(gs_ddt_t* ddt, const char* fmt, ...)
     38 {
     39         char tmp[512] = {0};
     40         va_list args;
     41 
     42         va_start(args, fmt);
     43         vsnprintf(tmp, sizeof(tmp), fmt, args);
     44         va_end(args);
     45 
     46         int n = sizeof(ddt->tb) - strlen(ddt->tb) - 1;
     47         int resize = strlen(tmp)  - n;
     48         if (resize > 0) {
     49                 memmove(ddt->tb, ddt->tb + resize, sizeof(ddt->tb) - resize);
     50                 n = sizeof(ddt->tb) - strlen(ddt->tb) - 1;
     51         }
     52         strncat(ddt->tb, tmp, n);
     53 }
     54 
     55 void
     56 gs_ddt(gs_ddt_t* ddt, gs_gui_context_t* ctx, gs_gui_rect_t screen, const gs_gui_selector_desc_t* desc)
     57 {
     58         if (ddt->open) {
     59                 ddt->y = gs_interp_linear(ddt->y, screen.h * ddt->size, ddt->open_speed);
     60                 ddt->close_complete = 0;
     61         } else if (!ddt->open && ddt->y > 0 && !ddt->close_complete) {
     62                 ddt->y = gs_interp_linear(ddt->y, -1, ddt->close_speed);
     63         } else if (!ddt->open) {
     64                 ddt->close_complete = 1;
     65                 return;
     66         }
     67 
     68         const float sz = gs_min(ddt->y, 26);
     69         if (gs_gui_window_begin_ex(ctx, "gs_ddt_content", gs_gui_rect(screen.x, screen.y, screen.w, ddt->y - sz), NULL, NULL,
     70                                    GS_GUI_OPT_FORCESETRECT | GS_GUI_OPT_NOTITLE | GS_GUI_OPT_NORESIZE | GS_GUI_OPT_NODOCK | GS_GUI_OPT_FORCEFOCUS | GS_GUI_OPT_HOLDFOCUS)) {
     71                 gs_gui_layout_row(ctx, 1, (int[]){-1}, 0);
     72                 gs_gui_text(ctx, ddt->tb);
     73                 if (ddt->autoscroll) gs_gui_get_current_container(ctx)->scroll.y = sizeof(ddt->tb)*7+100;
     74                 gs_gui_container_t* ctn = gs_gui_get_current_container(ctx);
     75                 gs_gui_bring_to_front(ctx, ctn);
     76                 gs_gui_window_end(ctx);
     77         }
     78 
     79         if (gs_gui_window_begin_ex(ctx, "gs_ddt_input", gs_gui_rect(screen.x, screen.y + ddt->y - sz, screen.w, sz), NULL, NULL,
     80                                    GS_GUI_OPT_FORCESETRECT | GS_GUI_OPT_NOTITLE | GS_GUI_OPT_NORESIZE | GS_GUI_OPT_NODOCK | GS_GUI_OPT_NOHOVER | GS_GUI_OPT_NOINTERACT)) {
     81                 int len = strlen(ddt->cb);
     82                 gs_gui_layout_row(ctx, 3, (int[]){14, len * 7+2, 10}, 0);
     83                 gs_gui_text(ctx, "$>");
     84                 gs_gui_text(ctx, ddt->cb);
     85 
     86                 // handle text input
     87                 int32_t n = gs_min(sizeof(ddt->cb) - len - 1, (int32_t) strlen(ctx->input_text));
     88                 if (!ddt->open || !ddt->last_open_state) {
     89 
     90                 } else if (ctx->key_pressed & GS_GUI_KEY_RETURN) {
     91                         gs_ddt_printf(ddt, "$ %s\n", ddt->cb);
     92 
     93                         if (*ddt->cb && ddt->commands) {
     94                                 char* tmp = ddt->cb;
     95                                 int argc = 1;
     96                                 while((tmp = strchr(tmp, ' '))) {
     97                                         argc++;
     98                                         tmp++;
     99                                 }
    100 
    101                                 tmp = ddt->cb;
    102                                 char* last_pos = ddt->cb;
    103                                 char* argv[argc];
    104                                 int i = 0;
    105                                 while((tmp = strchr(tmp, ' '))) {
    106                                         *tmp = 0;
    107                                         argv[i++] = last_pos;
    108                                         last_pos = ++tmp;
    109                                 }
    110                                 argv[argc-1] = last_pos;
    111 
    112                                 for (int i = 0; i < ddt->commands_len; i++) {
    113                                         if (ddt->commands[i].name && ddt->commands[i].func && strcmp(argv[0], ddt->commands[i].name) == 0) {
    114                                                 ddt->commands[i].func(argc, argv);
    115                                                 goto ddt_command_found;
    116                                         }
    117                                 }
    118                                 gs_ddt_printf(ddt, "[gs_ddt]: unrecognized command '%s'\n", argv[0]);
    119                         ddt_command_found:
    120                                 ddt->cb[0] = '\0';
    121                         }
    122                 } else if (ctx->key_pressed & GS_GUI_KEY_BACKSPACE && len > 0) {
    123                         // skip utf-8 continuation bytes
    124                         while ((ddt->cb[--len] & 0xc0) == 0x80 && len > 0);
    125                         ddt->cb[len] = '\0';
    126                 } else if (n > 0) {
    127                         memcpy(ddt->cb + len, ctx->input_text, n);
    128                         len += n;
    129                         ddt->cb[len] = '\0';
    130                 }
    131 
    132                 // blinking cursor
    133                 gs_gui_get_layout(ctx)->body.x -= 5;
    134                 if ((int)(gs_platform_elapsed_time() / 666.0f) & 1)
    135                         gs_gui_text(ctx, "|");
    136 
    137                 gs_gui_container_t* ctn = gs_gui_get_current_container(ctx);
    138                 gs_gui_bring_to_front(ctx, ctn);
    139 
    140                 gs_gui_window_end(ctx);
    141         }
    142 
    143         ddt->last_open_state = ddt->open;
    144 }
    145 #endif // GS_DDT_IMPL
    146 
    147 #endif // GS_DDT_H_