juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

form.c (3927B)


      1 /* form.c - navegacion y edicion de formularios. */
      2 #include <string.h>
      3 #include "form.h"
      4 #include "str.h"
      5 
      6 void form_begin(Form *f, const char *title)
      7 {
      8     memset(f, 0, sizeof *f);
      9     str_put(f->title, sizeof f->title, 0, title);
     10 }
     11 
     12 static Field *add(Form *f, int type, int id, const char *label)
     13 {
     14     if (f->n >= (int)(sizeof f->f / sizeof f->f[0])) return &f->f[f->n - 1];
     15     Field *x = &f->f[f->n++];
     16     memset(x, 0, sizeof *x);
     17     x->type = (uint8_t)type;
     18     x->id = (int16_t)id;
     19     str_put(x->label, sizeof x->label, 0, label);
     20     return x;
     21 }
     22 
     23 Field *form_button(Form *f, int id, const char *label) { return add(f, F_BUTTON, id, label); }
     24 Field *form_label(Form *f, const char *text) { return add(f, F_LABEL, -1, text); }
     25 
     26 Field *form_choice(Form *f, int id, const char *label, const char *const *choices, int n, int value)
     27 {
     28     Field *x = add(f, F_CHOICE, id, label);
     29     x->choices = choices;
     30     x->nchoices = (uint8_t)n;
     31     x->value = (int8_t)value;
     32     return x;
     33 }
     34 
     35 Field *form_text(Form *f, int id, const char *label, const char *init, int maxlen)
     36 {
     37     Field *x = add(f, F_TEXT, id, label);
     38     str_put(x->text, sizeof x->text, 0, init ? init : "");
     39     x->maxlen = (uint8_t)(maxlen < (int)sizeof x->text - 1 ? maxlen : (int)sizeof x->text - 1);
     40     return x;
     41 }
     42 
     43 Field *form_get(Form *f, int id)
     44 {
     45     for (int i = 0; i < f->n; i++) if (f->f[i].id == id) return &f->f[i];
     46     return 0;
     47 }
     48 
     49 void form_msg(Form *f, const char *msg, bool err)
     50 {
     51     str_put(f->msg, sizeof f->msg, 0, msg);
     52     f->msg_err = err;
     53 }
     54 
     55 static bool selectable(const Field *x) { return !x->hidden && !x->disabled && x->type != F_LABEL; }
     56 
     57 static void fix_cursor(Form *f, int dir)
     58 {
     59     for (int k = 0; k < f->n; k++) {
     60         if (f->cur < 0) f->cur = f->n - 1;
     61         if (f->cur >= f->n) f->cur = 0;
     62         if (selectable(&f->f[f->cur])) return;
     63         f->cur += dir;
     64     }
     65 }
     66 
     67 int form_key(Form *f, int key)
     68 {
     69     if (!f->n) return key == K_BACK ? FORM_CANCEL : FORM_NONE;
     70     fix_cursor(f, 1);
     71     Field *x = &f->f[f->cur];
     72     switch (key) {
     73     case K_UP:   f->cur--; fix_cursor(f, -1); return FORM_NONE;
     74     case K_DOWN: case K_TAB: f->cur++; fix_cursor(f, 1); return FORM_NONE;
     75     case K_BACK: return FORM_CANCEL;
     76     case K_LEFT: case K_RIGHT:
     77         if (x->type == F_CHOICE && x->nchoices)
     78             x->value = (int8_t)((x->value + (key == K_RIGHT ? 1 : x->nchoices - 1)) % x->nchoices);
     79         return FORM_NONE;
     80     case K_OK:
     81         if (x->type == F_BUTTON) return x->id;
     82         if (x->type == F_CHOICE && x->nchoices) { x->value = (int8_t)((x->value + 1) % x->nchoices); return FORM_NONE; }
     83         f->cur++; fix_cursor(f, 1);
     84         return FORM_NONE;
     85     case K_BKSP:
     86         if (x->type == F_TEXT) {
     87             int n = (int)strlen(x->text);
     88             while (n > 0 && ((unsigned char)x->text[n - 1] & 0xC0) == 0x80) n--;   /* utf-8 */
     89             if (n > 0) x->text[n - 1] = 0;
     90         }
     91         return FORM_NONE;
     92     default:
     93         if (x->type == F_TEXT && key >= 32 && key < 256 && (int)strlen(x->text) < x->maxlen) {
     94             int n = (int)strlen(x->text);
     95             if (key < 128) { x->text[n] = (char)key; x->text[n + 1] = 0; }
     96             else if (n + 2 <= x->maxlen) {           /* latin-1 -> utf-8 */
     97                 x->text[n] = (char)(0xC0 | (key >> 6));
     98                 x->text[n + 1] = (char)(0x80 | (key & 0x3F));
     99                 x->text[n + 2] = 0;
    100             }
    101         }
    102         return FORM_NONE;
    103     }
    104 }
    105 
    106 int form_click(Form *f, int index)
    107 {
    108     if (index < 0 || index >= f->n || !selectable(&f->f[index])) return FORM_NONE;
    109     f->cur = index;
    110     return form_key(f, K_OK);
    111 }
    112 
    113 const char *form_shown(const Field *x, char *buf, int n)
    114 {
    115     if (!x->secret) return x->text;
    116     int k = 0;
    117     for (const char *p = x->text; *p && k < n - 1; p++)
    118         if (((unsigned char)*p & 0xC0) != 0x80) buf[k++] = '*';   /* un asterisco por caracter utf-8 */
    119     buf[k] = 0;
    120     return buf;
    121 }