diff --git a/source/src/console.cpp b/source/src/console.cpp index b0eec651..078d996c 100644 --- a/source/src/console.cpp +++ b/source/src/console.cpp @@ -163,10 +163,13 @@ keym *findbind(const char *key) return NULL; } -keym *findbinda(const char *action, int type) +keym **findbinda(const char *action, int type) { - loopv(keyms) if(!strcasecmp(keyms[i].actions[type], action)) return &keyms[i]; - return NULL; + static vector res; + res.setsize(0); + loopv(keyms) if(!strcasecmp(keyms[i].actions[type], action)) res.add(&keyms[i]); + res.add(NULL); + return res.getbuf(); } keym *findbindc(int code) diff --git a/source/src/menus.cpp b/source/src/menus.cpp index 20aa8a8f..cb2d6a8d 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -677,10 +677,14 @@ struct mitemkeyinput : mitem { char *text, *bindcmd; const char *keyname; + vector newkeys; + int isup, bindtype; + string keynames; static const char *unknown, *empty; bool capture; - mitemkeyinput(gmenu *parent, char *text, char *bindcmd, color *bgcolor) : mitem(parent, bgcolor, mitem::TYPE_KEYINPUT), text(text), bindcmd(bindcmd), keyname(NULL), capture(false) {}; + mitemkeyinput(gmenu *parent, char *text, char *bindcmd, color *bgcolor) : mitem(parent, bgcolor, mitem::TYPE_KEYINPUT), text(text), bindcmd(bindcmd), + keyname(NULL), isup(0), bindtype(keym::ACTION_DEFAULT), capture(false) {}; ~mitemkeyinput() { @@ -701,31 +705,54 @@ struct mitemkeyinput : mitem virtual void init() { - displaycurrentbind(); + keynames[0] = 0; + for(keym **km = findbinda(bindcmd, bindtype); *km; km++) concatformatstring(keynames, " + %s", (*km)->name); + keyname = *keynames ? keynames + 3 : unknown; capture = false; } virtual int select() { capture = true; + isup = 0; keyname = empty; + newkeys.setsize(0); + keynames[0] = '\0'; return 0; } virtual void key(int code, bool isdown, int unicode) { - if(!capture || code < -5 || code > SDLK_MENU) return; - keym *km; - while((km = findbinda(bindcmd))) { bindkey(km, ""); } // clear existing binds to this cmd - if(bindc(code, bindcmd)) parent->init(); // re-init all bindings - else conoutf("\f3could not bind key"); + if(!capture || code < -5 || code > SDLK_MENU || !findbindc(code)) return; + if(code == SDLK_ESCAPE) + { + capture = false; + parent->init(); + return; + } + bool known = newkeys.find(code) >= 0; + if(isdown) + { + if(!known) + { + newkeys.add(code); + concatformatstring(keynames, "%s + ", findbindc(code)->name); + keyname = keynames; + } + } + else + { + if(known && ++isup == newkeys.length()) + { + for(keym **km = findbinda(bindcmd, bindtype); *km; km++) bindkey(*km, "", bindtype); // clear existing binds to this cmd + bool bindfailed = false; + loopv(newkeys) bindfailed = !bindc(newkeys[i], bindcmd, bindtype) || bindfailed; + if(bindfailed) conoutf("\f3could not bind key"); + else parent->init(); // show new keys + } + } } - void displaycurrentbind() - { - keym *km = findbinda(bindcmd); - keyname = km ? km->name : unknown; - } }; const char *mitemkeyinput::unknown = "?"; @@ -1101,6 +1128,17 @@ bool menukey(int code, bool isdown, int unicode, SDLMod mod) { if(!curmenu) return false; int n = curmenu->items.length(), menusel = curmenu->menusel; + + if(curmenu->items.inrange(menusel)) + { + mitem *m = curmenu->items[menusel]; + if(m->mitemtype == mitem::TYPE_KEYINPUT && ((mitemkeyinput *)m)->capture) + { + m->key(code, isdown, unicode); + return true; + } + } + if(isdown) { bool hasdesc = false; @@ -1108,16 +1146,6 @@ bool menukey(int code, bool isdown, int unicode, SDLMod mod) //int pagesize = MAXMENU - (curmenu->header ? 2 : 0) - (curmenu->footer || hasdesc ? 2 : 0); // FIXME: footer-length int pagesize = MAXMENU - (curmenu->header ? 2 : 0) - (curmenu->footer ? (curmenu->footlen?(curmenu->footlen+1):2) : (hasdesc ? 2 : 0)); // FIXME: footer-length - if(curmenu->items.inrange(menusel)) - { - mitem *m = curmenu->items[menusel]; - if(m->mitemtype == mitem::TYPE_KEYINPUT && ((mitemkeyinput *)m)->capture && code != SDLK_ESCAPE) - { - m->key(code, isdown, unicode); - return true; - } - } - switch(code) { case SDLK_PAGEUP: menusel -= pagesize; break; diff --git a/source/src/protos.h b/source/src/protos.h index 18b864bd..4aa1818a 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -157,8 +157,9 @@ struct keym extern keym *keypressed; extern bool bindkey(keym *km, const char *action, int state = keym::ACTION_DEFAULT); -extern keym *findbinda(const char *action, int type = keym::ACTION_DEFAULT); +extern keym **findbinda(const char *action, int type = keym::ACTION_DEFAULT); extern bool bindc(int code, const char *action, int type = keym::ACTION_DEFAULT); +extern keym *findbindc(int code); // menus extern void rendermenu();