gl: clear w, h on reinit
[libpicofe.git] / input.c
diff --git a/input.c b/input.c
index 8030e1f..4f91a55 100644 (file)
--- a/input.c
+++ b/input.c
@@ -43,6 +43,8 @@ static int in_have_async_devs = 0;
 static int in_probe_dev_id;
 static int menu_key_state = 0;
 static int menu_last_used_dev = 0;
+static int menu_key_prev = 0;
+static int menu_key_repeat = 0;
 
 #define DRV(id) in_drivers[id]
 
@@ -50,25 +52,26 @@ static int menu_last_used_dev = 0;
 static int *in_alloc_binds(int drv_id, int key_count)
 {
        const struct in_default_bind *defbinds;
-       int *binds;
+       int *binds, *binds_d;
        int i;
 
        binds = calloc(key_count * IN_BINDTYPE_COUNT * 2, sizeof(binds[0]));
        if (binds == NULL)
                return NULL;
 
+       binds_d = binds + key_count * IN_BINDTYPE_COUNT;
+
+       /* always have a copy of defbinds */
        defbinds = DRV(drv_id).defbinds;
        if (defbinds != NULL) {
                for (i = 0; ; i++) {
-                       if (defbinds[i].bit == 0 && defbinds[i].code == 0)
+                       if (defbinds[i].code == 0 && defbinds[i].btype == 0
+                           && defbinds[i].bit == 0)
                                break;
-                       binds[IN_BIND_OFFS(defbinds[i].code, defbinds[i].btype)] =
+
+                       binds_d[IN_BIND_OFFS(defbinds[i].code, defbinds[i].btype)] |=
                                1 << defbinds[i].bit;
                }
-
-               /* always have a copy of defbinds */
-               memcpy(binds + key_count * IN_BINDTYPE_COUNT, binds,
-                       sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT);
        }
 
        return binds;
@@ -140,6 +143,9 @@ void in_register(const char *nname, int drv_fd_hnd, void *drv_data,
                return;
        }
 
+       memcpy(binds, binds + key_count * IN_BINDTYPE_COUNT,
+               sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT);
+
        in_devices[i].name = tmp;
        in_devices[i].binds = binds;
        in_devices[i].key_count = key_count;
@@ -246,7 +252,7 @@ void in_probe(void)
 
        for (i = 0; i < in_driver_count; i++) {
                in_probe_dev_id = i;
-               in_drivers[i].probe();
+               in_drivers[i].probe(&DRV(i));
        }
 
        /* get rid of devs without binds and probes */
@@ -427,53 +433,46 @@ finish:
 int in_menu_wait_any(char *charcode, int timeout_ms)
 {
        int keys_old = menu_key_state;
+       int ret;
+       int dev_id = 0;
 
-       while (1)
-       {
-               int code, is_down = 0, dev_id = 0;
+       menu_key_prev = menu_key_state;
 
-               code = in_update_keycode(&dev_id, &is_down, charcode, timeout_ms);
-               if (code < 0)
-                       break;
+       in_update_keycode(&dev_id, NULL, charcode, timeout_ms);
 
-               if (keys_old != menu_key_state) {
-                       menu_last_used_dev = dev_id;
-                       break;
-               }
-       }
+       if (keys_old != menu_key_state)
+               menu_last_used_dev = dev_id;
 
-       return menu_key_state;
+       ret = menu_key_state;
+       if (ret == 0)
+               menu_key_prev = 0;
+
+       return ret;
 }
 
 /* wait for menu input, do autorepeat */
 int in_menu_wait(int interesting, char *charcode, int autorep_delay_ms)
 {
-       static int inp_prev = 0;
-       static int repeats = 0;
-       int ret, release = 0, wait = 450;
+       int ret, wait = 450;
 
-       if (repeats)
+       if (menu_key_repeat)
                wait = autorep_delay_ms;
 
-       ret = in_menu_wait_any(charcode, wait);
-       if (ret == inp_prev)
-               repeats++;
-
-       while (!(ret & interesting)) {
-               ret = in_menu_wait_any(charcode, -1);
-               release = 1;
-       }
-
-       if (release || ret != inp_prev)
-               repeats = 0;
-
-       inp_prev = ret;
+       /* wait until either key repeat or a new key has been pressed */
+#ifdef SDL_REDRAW_EVT
+       interesting |= PBTN_RDRAW;
+#endif
+       do {
+               ret = in_menu_wait_any(charcode, wait);
+               if (ret == 0 || ret != menu_key_prev)
+                       menu_key_repeat = 0;
+               else
+                       menu_key_repeat++;
+               wait = -1;
+       } while (!(ret & interesting));
 
        /* we don't need diagonals in menus */
-       if ((ret & PBTN_UP)   && (ret & PBTN_LEFT))  ret &= ~PBTN_LEFT;
-       if ((ret & PBTN_UP)   && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT;
-       if ((ret & PBTN_DOWN) && (ret & PBTN_LEFT))  ret &= ~PBTN_LEFT;
-       if ((ret & PBTN_DOWN) && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT;
+       if (ret & (PBTN_UP|PBTN_DOWN))  ret &= ~(PBTN_LEFT|PBTN_RIGHT);
 
        return ret;
 }
@@ -490,6 +489,8 @@ const int *in_get_dev_def_binds(int dev_id)
        in_dev_t *dev = get_dev(dev_id);
        if (dev == NULL)
                return NULL;
+       if (dev->binds == NULL)
+               return NULL;
 
        return dev->binds + dev->key_count * IN_BINDTYPE_COUNT;
 }
@@ -514,6 +515,9 @@ int in_get_config(int dev_id, int what, void *val)
        case IN_CFG_KEY_NAMES:
                return -1; /* not implemented */
        default:
+               if (!dev->probed)
+                       return -1;
+
                return DRV(dev->drv_id).get_config(dev->drv_data, what, ival);
        }
 
@@ -527,19 +531,22 @@ static int in_set_blocking(int is_blocking)
        /* have_async_devs means we will have to do all reads async anyway.. */
        if (!in_have_async_devs) {
                for (i = 0; i < in_dev_count; i++) {
-                       if (in_devices[i].probed)
-                               DRV(in_devices[i].drv_id).set_config(in_devices[i].drv_data,
-                                                                    IN_CFG_BLOCKING, is_blocking);
+                       if (!in_devices[i].probed)
+                               continue;
+
+                       DRV(in_devices[i].drv_id).set_config(
+                               in_devices[i].drv_data, IN_CFG_BLOCKING,
+                               is_blocking);
                }
        }
 
-       menu_key_state = 0;
-
        /* flush events */
        do {
                ret = in_update_keycode(NULL, NULL, NULL, 0);
        } while (ret >= 0);
 
+       menu_key_state = 0;
+
        return 0;
 }
 
@@ -769,7 +776,7 @@ int in_config_parse_dev(const char *name)
        }
 
        if (drv_id < 0) {
-               lprintf("input: missing driver for %s\n", name);
+               lprintf("input: missing driver for '%s'\n", name);
                return -1;
        }
 
@@ -787,7 +794,8 @@ int in_config_parse_dev(const char *name)
                for (i = 0; i < IN_MAX_DEVS; i++)
                        if (in_devices[i].name == NULL) break;
                if (i >= IN_MAX_DEVS) {
-                       lprintf("input: too many devices, can't add %s\n", name);
+                       lprintf("input: too many devices, can't add '%s'\n",
+                               name);
                        return -1;
                }
        }
@@ -798,7 +806,8 @@ int in_config_parse_dev(const char *name)
        if (in_devices[i].name == NULL)
                return -1;
 
-       in_devices[i].key_names = DRV(drv_id).get_key_names(&in_devices[i].key_count);
+       in_devices[i].key_names = DRV(drv_id).get_key_names(&DRV(drv_id),
+                               &in_devices[i].key_count);
        in_devices[i].drv_id = drv_id;
 
        if (i + 1 > in_dev_count)
@@ -851,7 +860,8 @@ int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type)
        }
 
        if (kc < 0 || kc >= dev->key_count) {
-               lprintf("input: bad key: %s\n", key);
+               lprintf("input: bad key: '%s' for device '%s'\n",
+                       key, dev->name);
                return -1;
        }
 
@@ -876,7 +886,7 @@ void in_clean_binds(void)
                int ret, count, *binds, *def_binds;
                in_dev_t *dev = &in_devices[i];
 
-               if (dev->binds == NULL || dev->drv_data == NULL)
+               if (dev->binds == NULL || !dev->probed)
                        continue;
 
                count = dev->key_count;
@@ -901,8 +911,25 @@ void in_debug_dump(void)
                in_dev_t *d = &in_devices[i];
                if (!d->probed && d->name == NULL && d->binds == NULL)
                        continue;
-               lprintf("%d %3d %6c %5c %s\n", i, d->drv_id, d->probed ? 'y' : 'n',
+               lprintf("%d %3d %6c %5c %s\n", i, d->drv_id,
+                       d->probed ? 'y' : 'n',
                        d->binds ? 'y' : 'n', d->name);
+#if 0
+               if (d->binds) {
+                       int kc, o, t, h;
+                       for (kc = 0; kc < d->key_count; kc++) {
+                               o = IN_BIND_OFFS(kc, 0);
+                               for (t = h = 0; t < IN_BINDTYPE_COUNT; t++)
+                                       h |= d->binds[o + t];
+                               if (h == 0)
+                                       continue;
+                               lprintf("  [%3d] =", kc);
+                               for (t = 0; t < IN_BINDTYPE_COUNT; t++)
+                                       printf(" %x", d->binds[o + t]);
+                               printf("\n");
+                       }
+               }
+#endif
        }
 }
 
@@ -922,7 +949,8 @@ static const char *in_def_get_key_name(int keycode) { return NULL; }
        if (d.f == NULL) d.f = in_def_##f
 
 /* to be called by drivers */
-int in_register_driver(const in_drv_t *drv, const struct in_default_bind *defbinds)
+int in_register_driver(const in_drv_t *drv,
+                       const struct in_default_bind *defbinds, const void *pdata)
 {
        int count_new = in_driver_count + 1;
        in_drv_t *new_drivers;
@@ -944,7 +972,9 @@ int in_register_driver(const in_drv_t *drv, const struct in_default_bind *defbin
        CHECK_ADD_STUB(new_drivers[in_driver_count], menu_translate);
        CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_code);
        CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_name);
-       if (defbinds != NULL)
+       if (pdata)
+               new_drivers[in_driver_count].pdata = pdata;
+       if (defbinds)
                new_drivers[in_driver_count].defbinds = defbinds;
        in_drivers = new_drivers;
        in_driver_count = count_new;