diff options
Diffstat (limited to 'src/engine/console.cpp')
| -rw-r--r-- | src/engine/console.cpp | 1110 |
1 files changed, 553 insertions, 557 deletions
diff --git a/src/engine/console.cpp b/src/engine/console.cpp index d6e83a1..c979215 100644 --- a/src/engine/console.cpp +++ b/src/engine/console.cpp @@ -18,33 +18,33 @@ VARFP(maxcon, 10, 200, MAXCONLINES, { while(conlines.length() > maxcon) delete[] VARP(contags, 0, 3, 3); -void conline(int type, const char *sf) // add a line to the console buffer -{ - char *buf = NULL; - if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) - { - int prev = conlines.removing(i).type; - if(!(prev&CON_TAG_MASK)) break; - if(type == prev) - { - buf = conlines.remove(i).line; - break; - } - } - if(!buf) buf = conlines.length() >= maxcon ? conlines.remove().line : newstring("", CONSTRLEN-1); - cline &cl = conlines.add(); - cl.line = buf; - cl.type = type; - cl.outtime = totalmillis; // for how long to keep line on screen - copystring(cl.line, sf, CONSTRLEN); +void conline(int type, const char *sf) // add a line to the console buffer +{ + char *buf = NULL; + if(type&CON_TAG_MASK) for(int i = conlines.length()-1; i >= max(conlines.length()-contags, 0); i--) + { + int prev = conlines.removing(i).type; + if(!(prev&CON_TAG_MASK)) break; + if(type == prev) + { + buf = conlines.remove(i).line; + break; + } + } + if(!buf) buf = conlines.length() >= maxcon ? conlines.remove().line : newstring("", CONSTRLEN-1); + cline &cl = conlines.add(); + cl.line = buf; + cl.type = type; + cl.outtime = totalmillis; // for how long to keep line on screen + copystring(cl.line, sf, CONSTRLEN); } void conoutfv(int type, const char *fmt, va_list args) { - static char buf[CONSTRLEN]; - vformatstring(buf, fmt, args, sizeof(buf)); - conline(type, buf); - logoutf("%s", buf); + static char buf[CONSTRLEN]; + vformatstring(buf, fmt, args, sizeof(buf)); + conline(type, buf); + logoutf("%s", buf); } VAR(fullconsole, 0, 0, 1); @@ -52,14 +52,14 @@ ICOMMAND(toggleconsole, "", (), { fullconsole ^= 1; }); int rendercommand(int x, int y, int w) { - if(commandmillis < 0) return 0; + if(commandmillis < 0) return 0; - defformatstring(s, "%s %s", commandprompt ? commandprompt : ">", commandbuf); - int width, height; - text_bounds(s, width, height, w); - y -= height; - draw_text(s, x, y, 0xFF, 0xFF, 0xFF, 0xFF, (commandpos>=0) ? (commandpos+1+(commandprompt?strlen(commandprompt):1)) : strlen(s), w); - return height; + defformatstring(s, "%s %s", commandprompt ? commandprompt : ">", commandbuf); + int width, height; + text_bounds(s, width, height, w); + y -= height; + draw_text(s, x, y, 0xFF, 0xFF, 0xFF, 0xFF, (commandpos>=0) ? (commandpos+1+(commandprompt?strlen(commandprompt):1)) : strlen(s), w); + return height; } VARP(consize, 0, 5, 100); @@ -76,19 +76,19 @@ int conskip = 0, miniconskip = 0; void setconskip(int &skip, int filter, int n) { - filter &= CON_FLAGS; - int offset = abs(n), dir = n < 0 ? -1 : 1; - skip = clamp(skip, 0, conlines.length()-1); - while(offset) - { - skip += dir; - if(!conlines.inrange(skip)) - { - skip = clamp(skip, 0, conlines.length()-1); - return; - } - if(conlines[skip].type&filter) --offset; - } + filter &= CON_FLAGS; + int offset = abs(n), dir = n < 0 ? -1 : 1; + skip = clamp(skip, 0, conlines.length()-1); + while(offset) + { + skip += dir; + if(!conlines.inrange(skip)) + { + skip = clamp(skip, 0, conlines.length()-1); + return; + } + if(conlines[skip].type&filter) --offset; + } } ICOMMAND(conskip, "i", (int *n), setconskip(conskip, fullconsole ? fullconfilter : confilter, *n)); @@ -98,94 +98,94 @@ ICOMMAND(clearconsole, "", (), { while(conlines.length()) delete[] conlines.pop( int drawconlines(int conskip, int confade, int conwidth, int conheight, int conoff, int filter, int y = 0, int dir = 1) { - filter &= CON_FLAGS; - int numl = conlines.length(), offset = min(conskip, numl); - - if(confade) - { - if(!conskip) - { - numl = 0; - loopvrev(conlines) if(totalmillis-conlines[i].outtime < confade*1000) { numl = i+1; break; } - } - else offset--; - } - - int totalheight = 0; - loopi(numl) //determine visible height - { - // shuffle backwards to fill if necessary - int idx = offset+i < numl ? offset+i : --offset; - if(!(conlines[idx].type&filter)) continue; - char *line = conlines[idx].line; - int width, height; - text_bounds(line, width, height, conwidth); - if(totalheight + height > conheight) { numl = i; if(offset == idx) ++offset; break; } - totalheight += height; - } - if(dir > 0) y = conoff; - loopi(numl) - { - int idx = offset + (dir > 0 ? numl-i-1 : i); - if(!(conlines[idx].type&filter)) continue; - char *line = conlines[idx].line; - int width, height; - text_bounds(line, width, height, conwidth); - if(dir <= 0) y -= height; - draw_text(line, conoff, y, 0xFF, 0xFF, 0xFF, 0xFF, -1, conwidth); - if(dir > 0) y += height; - } - return y+conoff; -} - -int renderconsole(int w, int h, int abovehud) // render buffer taking into account time & scrolling -{ - int conpad = fullconsole ? 0 : FONTH/4, - conoff = fullconsole ? FONTH : FONTH/3, - conheight = min(fullconsole ? ((h*fullconsize/100)/FONTH)*FONTH : FONTH*consize, h - 2*(conpad + conoff)), - conwidth = w - 2*(conpad + conoff) - (fullconsole ? 0 : game::clipconsole(w, h)); - - extern void consolebox(int x1, int y1, int x2, int y2); - if(fullconsole) consolebox(conpad, conpad, conwidth+conpad+2*conoff, conheight+conpad+2*conoff); - - int y = drawconlines(conskip, fullconsole ? 0 : confade, conwidth, conheight, conpad+conoff, fullconsole ? fullconfilter : confilter); - if(!fullconsole && (miniconsize && miniconwidth)) - drawconlines(miniconskip, miniconfade, (miniconwidth*(w - 2*(conpad + conoff)))/100, min(FONTH*miniconsize, abovehud - y), conpad+conoff, miniconfilter, abovehud, -1); - return fullconsole ? conheight + 2*(conpad + conoff) : y; + filter &= CON_FLAGS; + int numl = conlines.length(), offset = min(conskip, numl); + + if(confade) + { + if(!conskip) + { + numl = 0; + loopvrev(conlines) if(totalmillis-conlines[i].outtime < confade*1000) { numl = i+1; break; } + } + else offset--; + } + + int totalheight = 0; + loopi(numl) //determine visible height + { + // shuffle backwards to fill if necessary + int idx = offset+i < numl ? offset+i : --offset; + if(!(conlines[idx].type&filter)) continue; + char *line = conlines[idx].line; + int width, height; + text_bounds(line, width, height, conwidth); + if(totalheight + height > conheight) { numl = i; if(offset == idx) ++offset; break; } + totalheight += height; + } + if(dir > 0) y = conoff; + loopi(numl) + { + int idx = offset + (dir > 0 ? numl-i-1 : i); + if(!(conlines[idx].type&filter)) continue; + char *line = conlines[idx].line; + int width, height; + text_bounds(line, width, height, conwidth); + if(dir <= 0) y -= height; + draw_text(line, conoff, y, 0xFF, 0xFF, 0xFF, 0xFF, -1, conwidth); + if(dir > 0) y += height; + } + return y+conoff; +} + +int renderconsole(int w, int h, int abovehud) // render buffer taking into account time & scrolling +{ + int conpad = fullconsole ? 0 : FONTH/4, + conoff = fullconsole ? FONTH : FONTH/3, + conheight = min(fullconsole ? ((h*fullconsize/100)/FONTH)*FONTH : FONTH*consize, h - 2*(conpad + conoff)), + conwidth = w - 2*(conpad + conoff) - (fullconsole ? 0 : game::clipconsole(w, h)); + + extern void consolebox(int x1, int y1, int x2, int y2); + if(fullconsole) consolebox(conpad, conpad, conwidth+conpad+2*conoff, conheight+conpad+2*conoff); + + int y = drawconlines(conskip, fullconsole ? 0 : confade, conwidth, conheight, conpad+conoff, fullconsole ? fullconfilter : confilter); + if(!fullconsole && (miniconsize && miniconwidth)) + drawconlines(miniconskip, miniconfade, (miniconwidth*(w - 2*(conpad + conoff)))/100, min(FONTH*miniconsize, abovehud - y), conpad+conoff, miniconfilter, abovehud, -1); + return fullconsole ? conheight + 2*(conpad + conoff) : y; } // keymap is defined externally in keymap.cfg struct keym { - enum - { - ACTION_DEFAULT = 0, - ACTION_SPECTATOR, - ACTION_EDITING, - NUMACTIONS - }; - - int code; - char *name; - char *actions[NUMACTIONS]; - bool pressed; - - keym() : code(-1), name(NULL), pressed(false) { loopi(NUMACTIONS) actions[i] = newstring(""); } - ~keym() { DELETEA(name); loopi(NUMACTIONS) DELETEA(actions[i]); } + enum + { + ACTION_DEFAULT = 0, + ACTION_SPECTATOR, + ACTION_EDITING, + NUMACTIONS + }; + + int code; + char *name; + char *actions[NUMACTIONS]; + bool pressed; + + keym() : code(-1), name(NULL), pressed(false) { loopi(NUMACTIONS) actions[i] = newstring(""); } + ~keym() { DELETEA(name); loopi(NUMACTIONS) DELETEA(actions[i]); } }; hashtable<int, keym> keyms(128); void keymap(int *code, char *key) { - if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override keymap %d", *code); return; } - keym &km = keyms[*code]; - km.code = *code; - DELETEA(km.name); - km.name = newstring(key); + if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override keymap %d", *code); return; } + keym &km = keyms[*code]; + km.code = *code; + DELETEA(km.name); + km.name = newstring(key); } - + COMMAND(keymap, "is"); keym *keypressed = NULL; @@ -193,83 +193,83 @@ char *keyaction = NULL; const char *getkeyname(int code) { - keym *km = keyms.access(code); - return km ? km->name : NULL; + keym *km = keyms.access(code); + return km ? km->name : NULL; } void searchbinds(char *action, int type) { - vector<char> names; - enumerate(keyms, keym, km, - { - if(!strcmp(km.actions[type], action)) - { - if(names.length()) names.add(' '); - names.put(km.name, strlen(km.name)); - } - }); - names.add('\0'); - result(names.getbuf()); + vector<char> names; + enumerate(keyms, keym, km, + { + if(!strcmp(km.actions[type], action)) + { + if(names.length()) names.add(' '); + names.put(km.name, strlen(km.name)); + } + }); + names.add('\0'); + result(names.getbuf()); } keym *findbind(char *key) { - enumerate(keyms, keym, km, - { - if(!strcasecmp(km.name, key)) return &km; - }); - return NULL; -} - + enumerate(keyms, keym, km, + { + if(!strcasecmp(km.name, key)) return &km; + }); + return NULL; +} + void getbind(char *key, int type) { - keym *km = findbind(key); - result(km ? km->actions[type] : ""); -} + keym *km = findbind(key); + result(km ? km->actions[type] : ""); +} void bindkey(char *key, char *action, int state, const char *cmd) { - if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override %s \"%s\"", cmd, key); return; } - keym *km = findbind(key); - if(!km) { conoutf(CON_ERROR, "unknown key \"%s\"", key); return; } - char *&binding = km->actions[state]; - if(!keypressed || keyaction!=binding) delete[] binding; - // trim white-space to make searchbinds more reliable - while(iscubespace(*action)) action++; - int len = strlen(action); - while(len>0 && iscubespace(action[len-1])) len--; - binding = newstring(action, len); + if(identflags&IDF_OVERRIDDEN) { conoutf(CON_ERROR, "cannot override %s \"%s\"", cmd, key); return; } + keym *km = findbind(key); + if(!km) { conoutf(CON_ERROR, "unknown key \"%s\"", key); return; } + char *&binding = km->actions[state]; + if(!keypressed || keyaction!=binding) delete[] binding; + // trim white-space to make searchbinds more reliable + while(iscubespace(*action)) action++; + int len = strlen(action); + while(len>0 && iscubespace(action[len-1])) len--; + binding = newstring(action, len); } -ICOMMAND(bind, "ss", (char *key, char *action), bindkey(key, action, keym::ACTION_DEFAULT, "bind")); +ICOMMAND(bind, "ss", (char *key, char *action), bindkey(key, action, keym::ACTION_DEFAULT, "bind")); ICOMMAND(specbind, "ss", (char *key, char *action), bindkey(key, action, keym::ACTION_SPECTATOR, "specbind")); ICOMMAND(editbind, "ss", (char *key, char *action), bindkey(key, action, keym::ACTION_EDITING, "editbind")); -ICOMMAND(getbind, "s", (char *key), getbind(key, keym::ACTION_DEFAULT)); +ICOMMAND(getbind, "s", (char *key), getbind(key, keym::ACTION_DEFAULT)); ICOMMAND(getspecbind, "s", (char *key), getbind(key, keym::ACTION_SPECTATOR)); ICOMMAND(geteditbind, "s", (char *key), getbind(key, keym::ACTION_EDITING)); -ICOMMAND(searchbinds, "s", (char *action), searchbinds(action, keym::ACTION_DEFAULT)); +ICOMMAND(searchbinds, "s", (char *action), searchbinds(action, keym::ACTION_DEFAULT)); ICOMMAND(searchspecbinds, "s", (char *action), searchbinds(action, keym::ACTION_SPECTATOR)); ICOMMAND(searcheditbinds, "s", (char *action), searchbinds(action, keym::ACTION_EDITING)); void inputcommand(char *init, char *action = NULL, char *prompt = NULL, char *flags = NULL) // turns input to the command line on or off { - commandmillis = init ? totalmillis : -1; - textinput(commandmillis >= 0, TI_CONSOLE); - keyrepeat(commandmillis >= 0, KR_CONSOLE); - copystring(commandbuf, init ? init : ""); - DELETEA(commandaction); - DELETEA(commandprompt); - commandpos = -1; - if(action && action[0]) commandaction = newstring(action); - if(prompt && prompt[0]) commandprompt = newstring(prompt); - commandflags = 0; - if(flags) while(*flags) switch(*flags++) - { - case 'c': commandflags |= CF_COMPLETE; break; - case 'x': commandflags |= CF_EXECUTE; break; - case 's': commandflags |= CF_COMPLETE|CF_EXECUTE; break; - } - else if(init) commandflags |= CF_COMPLETE|CF_EXECUTE; + commandmillis = init ? totalmillis : -1; + textinput(commandmillis >= 0, TI_CONSOLE); + keyrepeat(commandmillis >= 0, KR_CONSOLE); + copystring(commandbuf, init ? init : ""); + DELETEA(commandaction); + DELETEA(commandprompt); + commandpos = -1; + if(action && action[0]) commandaction = newstring(action); + if(prompt && prompt[0]) commandprompt = newstring(prompt); + commandflags = 0; + if(flags) while(*flags) switch(*flags++) + { + case 'c': commandflags |= CF_COMPLETE; break; + case 'x': commandflags |= CF_EXECUTE; break; + case 's': commandflags |= CF_COMPLETE|CF_EXECUTE; break; + } + else if(init) commandflags |= CF_COMPLETE|CF_EXECUTE; } ICOMMAND(saycommand, "C", (char *init), inputcommand(init)); @@ -277,66 +277,66 @@ COMMAND(inputcommand, "ssss"); void pasteconsole() { - if(!SDL_HasClipboardText()) return; - char *cb = SDL_GetClipboardText(); - if(!cb) return; - size_t cblen = strlen(cb), - commandlen = strlen(commandbuf), - decoded = decodeutf8((uchar *)&commandbuf[commandlen], sizeof(commandbuf)-1-commandlen, (const uchar *)cb, cblen); - commandbuf[commandlen + decoded] = '\0'; - SDL_free(cb); + if(!SDL_HasClipboardText()) return; + char *cb = SDL_GetClipboardText(); + if(!cb) return; + size_t cblen = strlen(cb), + commandlen = strlen(commandbuf), + decoded = decodeutf8((uchar *)&commandbuf[commandlen], sizeof(commandbuf)-1-commandlen, (const uchar *)cb, cblen); + commandbuf[commandlen + decoded] = '\0'; + SDL_free(cb); } struct hline { - char *buf, *action, *prompt; - int flags; - - hline() : buf(NULL), action(NULL), prompt(NULL), flags(0) {} - ~hline() - { - DELETEA(buf); - DELETEA(action); - DELETEA(prompt); - } - - void restore() - { - copystring(commandbuf, buf); - if(commandpos >= (int)strlen(commandbuf)) commandpos = -1; - DELETEA(commandaction); - DELETEA(commandprompt); - if(action) commandaction = newstring(action); - if(prompt) commandprompt = newstring(prompt); - commandflags = flags; - } - - bool shouldsave() - { - return strcmp(commandbuf, buf) || - (commandaction ? !action || strcmp(commandaction, action) : action!=NULL) || - (commandprompt ? !prompt || strcmp(commandprompt, prompt) : prompt!=NULL) || - commandflags != flags; - } - - void save() - { - buf = newstring(commandbuf); - if(commandaction) action = newstring(commandaction); - if(commandprompt) prompt = newstring(commandprompt); - flags = commandflags; - } - - void run() - { - if(flags&CF_EXECUTE && buf[0]=='/') execute(buf+1); - else if(action) - { - alias("commandbuf", buf); - execute(action); - } - else game::toserver(buf); - } + char *buf, *action, *prompt; + int flags; + + hline() : buf(NULL), action(NULL), prompt(NULL), flags(0) {} + ~hline() + { + DELETEA(buf); + DELETEA(action); + DELETEA(prompt); + } + + void restore() + { + copystring(commandbuf, buf); + if(commandpos >= (int)strlen(commandbuf)) commandpos = -1; + DELETEA(commandaction); + DELETEA(commandprompt); + if(action) commandaction = newstring(action); + if(prompt) commandprompt = newstring(prompt); + commandflags = flags; + } + + bool shouldsave() + { + return strcmp(commandbuf, buf) || + (commandaction ? !action || strcmp(commandaction, action) : action!=NULL) || + (commandprompt ? !prompt || strcmp(commandprompt, prompt) : prompt!=NULL) || + commandflags != flags; + } + + void save() + { + buf = newstring(commandbuf); + if(commandaction) action = newstring(commandaction); + if(commandprompt) prompt = newstring(commandprompt); + flags = commandflags; + } + + void run() + { + if(flags&CF_EXECUTE && buf[0]=='/') execute(buf+1); + else if(action) + { + alias("commandbuf", buf); + execute(action); + } + else game::toserver(buf); + } }; vector<hline *> history; int histpos = 0; @@ -345,250 +345,246 @@ VARP(maxhistory, 0, 1000, 10000); void history_(int *n) { - static bool inhistory = false; - if(!inhistory && history.inrange(*n)) - { - inhistory = true; - history[history.length()-*n-1]->run(); - inhistory = false; - } + static bool inhistory = false; + if(!inhistory && history.inrange(*n)) + { + inhistory = true; + history[history.length()-*n-1]->run(); + inhistory = false; + } } COMMANDN(history, history_, "i"); struct releaseaction { - keym *key; - char *action; + keym *key; + char *action; }; vector<releaseaction> releaseactions; const char *addreleaseaction(char *s) { - if(!keypressed) { delete[] s; return NULL; } - releaseaction &ra = releaseactions.add(); - ra.key = keypressed; - ra.action = s; - return keypressed->name; + if(!keypressed) { delete[] s; return NULL; } + releaseaction &ra = releaseactions.add(); + ra.key = keypressed; + ra.action = s; + return keypressed->name; } void onrelease(const char *s) { - addreleaseaction(newstring(s)); + addreleaseaction(newstring(s)); } COMMAND(onrelease, "s"); void execbind(keym &k, bool isdown) { - loopv(releaseactions) - { - releaseaction &ra = releaseactions[i]; - if(ra.key==&k) - { - if(!isdown) execute(ra.action); - delete[] ra.action; - releaseactions.remove(i--); - } - } - if(isdown) - { - int state = keym::ACTION_DEFAULT; - if(!mainmenu) - { - if(editmode) state = keym::ACTION_EDITING; - else if(player->state==CS_SPECTATOR) state = keym::ACTION_SPECTATOR; - } - char *&action = k.actions[state][0] ? k.actions[state] : k.actions[keym::ACTION_DEFAULT]; - keyaction = action; - keypressed = &k; - execute(keyaction); - keypressed = NULL; - if(keyaction!=action) delete[] keyaction; - } - k.pressed = isdown; + loopv(releaseactions) + { + releaseaction &ra = releaseactions[i]; + if(ra.key==&k) + { + if(!isdown) execute(ra.action); + delete[] ra.action; + releaseactions.remove(i--); + } + } + if(isdown) + { + int state = keym::ACTION_DEFAULT; + if(!mainmenu) + { + if(editmode) state = keym::ACTION_EDITING; + else if(player->state==CS_SPECTATOR) state = keym::ACTION_SPECTATOR; + } + char *&action = k.actions[state][0] ? k.actions[state] : k.actions[keym::ACTION_DEFAULT]; + keyaction = action; + keypressed = &k; + execute(keyaction); + keypressed = NULL; + if(keyaction!=action) delete[] keyaction; + } + k.pressed = isdown; } bool consoleinput(const char *str, int len) { - if(commandmillis < 0) return false; - - resetcomplete(); - int cmdlen = (int)strlen(commandbuf), cmdspace = int(sizeof(commandbuf)) - (cmdlen+1); - len = min(len, cmdspace); - if(commandpos<0) - { - memcpy(&commandbuf[cmdlen], str, len); - } - else - { - memmove(&commandbuf[commandpos+len], &commandbuf[commandpos], cmdlen - commandpos); - memcpy(&commandbuf[commandpos], str, len); - commandpos += len; - } - commandbuf[cmdlen + len] = '\0'; - - return true; + if(commandmillis < 0) return false; + + resetcomplete(); + int cmdlen = (int)strlen(commandbuf), cmdspace = int(sizeof(commandbuf)) - (cmdlen+1); + len = min(len, cmdspace); + if(commandpos<0) + { + memcpy(&commandbuf[cmdlen], str, len); + } + else + { + memmove(&commandbuf[commandpos+len], &commandbuf[commandpos], cmdlen - commandpos); + memcpy(&commandbuf[commandpos], str, len); + commandpos += len; + } + commandbuf[cmdlen + len] = '\0'; + + return true; } bool consolekey(int code, bool isdown) { - if(commandmillis < 0) return false; - - #ifdef __APPLE__ - #define MOD_KEYS (KMOD_LGUI|KMOD_RGUI) - #else - #define MOD_KEYS (KMOD_LCTRL|KMOD_RCTRL) - #endif - - if(isdown) - { - switch(code) - { - case SDLK_RETURN: - case SDLK_KP_ENTER: - break; - - case SDLK_HOME: - if(strlen(commandbuf)) commandpos = 0; - break; - - case SDLK_END: - commandpos = -1; - break; - - case SDLK_DELETE: - { - int len = (int)strlen(commandbuf); - if(commandpos<0) break; - memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos); - resetcomplete(); - if(commandpos>=len-1) commandpos = -1; - break; - } - - case SDLK_BACKSPACE: - { - int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len; - if(i<1) break; - memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1); - resetcomplete(); - if(commandpos>0) commandpos--; - else if(!commandpos && len<=1) commandpos = -1; - break; - } - - case SDLK_LEFT: - if(commandpos>0) commandpos--; - else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1; - break; - - case SDLK_RIGHT: - if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1; - break; - - case SDLK_UP: - if(histpos > history.length()) histpos = history.length(); - if(histpos > 0) history[--histpos]->restore(); - break; - - case SDLK_DOWN: - if(histpos + 1 < history.length()) history[++histpos]->restore(); - break; - - case SDLK_TAB: - if(commandflags&CF_COMPLETE) - { - complete(commandbuf, sizeof(commandbuf), commandflags&CF_EXECUTE ? "/" : NULL); - if(commandpos>=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1; - } - break; - - case SDLK_v: - if(SDL_GetModState()&MOD_KEYS) pasteconsole(); - break; - } - } - else - { - if(code==SDLK_RETURN || code==SDLK_KP_ENTER) - { - hline *h = NULL; - if(commandbuf[0]) - { - if(history.empty() || history.last()->shouldsave()) - { - if(maxhistory && history.length() >= maxhistory) - { - loopi(history.length()-maxhistory+1) delete history[i]; - history.remove(0, history.length()-maxhistory+1); - } - history.add(h = new hline)->save(); - } - else h = history.last(); - } - histpos = history.length(); - inputcommand(NULL); - if(h) h->run(); - } - else if(code==SDLK_ESCAPE) - { - histpos = history.length(); - inputcommand(NULL); - } - } - - return true; + if(commandmillis < 0) return false; + +#define MOD_KEYS (KMOD_LCTRL|KMOD_RCTRL) + + if(isdown) + { + switch(code) + { + case SDLK_RETURN: + case SDLK_KP_ENTER: + break; + + case SDLK_HOME: + if(strlen(commandbuf)) commandpos = 0; + break; + + case SDLK_END: + commandpos = -1; + break; + + case SDLK_DELETE: + { + int len = (int)strlen(commandbuf); + if(commandpos<0) break; + memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos); + resetcomplete(); + if(commandpos>=len-1) commandpos = -1; + break; + } + + case SDLK_BACKSPACE: + { + int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len; + if(i<1) break; + memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1); + resetcomplete(); + if(commandpos>0) commandpos--; + else if(!commandpos && len<=1) commandpos = -1; + break; + } + + case SDLK_LEFT: + if(commandpos>0) commandpos--; + else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1; + break; + + case SDLK_RIGHT: + if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1; + break; + + case SDLK_UP: + if(histpos > history.length()) histpos = history.length(); + if(histpos > 0) history[--histpos]->restore(); + break; + + case SDLK_DOWN: + if(histpos + 1 < history.length()) history[++histpos]->restore(); + break; + + case SDLK_TAB: + if(commandflags&CF_COMPLETE) + { + complete(commandbuf, sizeof(commandbuf), commandflags&CF_EXECUTE ? "/" : NULL); + if(commandpos>=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1; + } + break; + + case SDLK_v: + if(SDL_GetModState()&MOD_KEYS) pasteconsole(); + break; + } + } + else + { + if(code==SDLK_RETURN || code==SDLK_KP_ENTER) + { + hline *h = NULL; + if(commandbuf[0]) + { + if(history.empty() || history.last()->shouldsave()) + { + if(maxhistory && history.length() >= maxhistory) + { + loopi(history.length()-maxhistory+1) delete history[i]; + history.remove(0, history.length()-maxhistory+1); + } + history.add(h = new hline)->save(); + } + else h = history.last(); + } + histpos = history.length(); + inputcommand(NULL); + if(h) h->run(); + } + else if(code==SDLK_ESCAPE) + { + histpos = history.length(); + inputcommand(NULL); + } + } + + return true; } void processtextinput(const char *str, int len) { - if(!g3d_input(str, len)) - consoleinput(str, len); + if(!g3d_input(str, len)) + consoleinput(str, len); } void processkey(int code, bool isdown, int modstate) { - switch(code) - { - case SDLK_LGUI: case SDLK_RGUI: - return; - } - keym *haskey = keyms.access(code); - if(haskey && haskey->pressed) execbind(*haskey, isdown); // allow pressed keys to release - else if(!g3d_key(code, isdown)) // 3D GUI mouse button intercept - { - if(!consolekey(code, isdown)) - { - if(modstate&KMOD_GUI) return; - if(haskey) execbind(*haskey, isdown); - } - } + switch(code) + { + case SDLK_LGUI: case SDLK_RGUI: + return; + } + keym *haskey = keyms.access(code); + if(haskey && haskey->pressed) execbind(*haskey, isdown); // allow pressed keys to release + else if(!g3d_key(code, isdown)) // 3D GUI mouse button intercept + { + if(!consolekey(code, isdown)) + { + if(modstate&KMOD_GUI) return; + if(haskey) execbind(*haskey, isdown); + } + } } void clear_console() { - keyms.clear(); + keyms.clear(); } void writebinds(stream *f) { - static const char * const cmds[3] = { "bind", "specbind", "editbind" }; - vector<keym *> binds; - enumerate(keyms, keym, km, binds.add(&km)); - binds.sortname(); - loopj(3) - { - loopv(binds) - { - keym &km = *binds[i]; - if(*km.actions[j]) - { - if(validateblock(km.actions[j])) f->printf("%s %s [%s]\n", cmds[j], escapestring(km.name), km.actions[j]); - else f->printf("%s %s %s\n", cmds[j], escapestring(km.name), escapestring(km.actions[j])); - } - } - } + static const char * const cmds[3] = { "bind", "specbind", "editbind" }; + vector<keym *> binds; + enumerate(keyms, keym, km, binds.add(&km)); + binds.sortname(); + loopj(3) + { + loopv(binds) + { + keym &km = *binds[i]; + if(*km.actions[j]) + { + if(validateblock(km.actions[j])) f->printf("%s %s [%s]\n", cmds[j], escapestring(km.name), km.actions[j]); + else f->printf("%s %s %s\n", cmds[j], escapestring(km.name), escapestring(km.actions[j])); + } + } + } } // tab-completion of all idents and base maps @@ -597,62 +593,62 @@ enum { FILES_DIR = 0, FILES_VAR, FILES_LIST }; struct fileskey { - int type; - const char *dir, *ext; + int type; + const char *dir, *ext; - fileskey() {} - fileskey(int type, const char *dir, const char *ext) : type(type), dir(dir), ext(ext) {} + fileskey() {} + fileskey(int type, const char *dir, const char *ext) : type(type), dir(dir), ext(ext) {} }; static void cleanfilesdir(char *dir) { - int dirlen = (int)strlen(dir); - while(dirlen > 0 && (dir[dirlen-1] == '/' || dir[dirlen-1] == '\\')) - dir[--dirlen] = '\0'; + int dirlen = (int)strlen(dir); + while(dirlen > 0 && (dir[dirlen-1] == '/' || dir[dirlen-1] == '\\')) + dir[--dirlen] = '\0'; } struct filesval { - int type; - char *dir, *ext; - vector<char *> files; - int millis; - - filesval(int type, const char *dir, const char *ext) : type(type), dir(newstring(dir)), ext(ext && ext[0] ? newstring(ext) : NULL), millis(-1) {} - ~filesval() { DELETEA(dir); DELETEA(ext); files.deletearrays(); } - - void update() - { - if((type!=FILES_DIR && type!=FILES_VAR) || millis >= commandmillis) return; - files.deletearrays(); - if(type==FILES_VAR) - { - string buf; - buf[0] = '\0'; - if(ident *id = readident(dir)) switch(id->type) - { - case ID_SVAR: copystring(buf, *id->storage.s); break; - case ID_ALIAS: copystring(buf, id->getstr()); break; - } - if(!buf[0]) copystring(buf, "."); - cleanfilesdir(buf); - listfiles(buf, ext, files); - } - else listfiles(dir, ext, files); - files.sort(); - loopv(files) if(i && !strcmp(files[i], files[i-1])) delete[] files.remove(i--); - millis = totalmillis; - } + int type; + char *dir, *ext; + vector<char *> files; + int millis; + + filesval(int type, const char *dir, const char *ext) : type(type), dir(newstring(dir)), ext(ext && ext[0] ? newstring(ext) : NULL), millis(-1) {} + ~filesval() { DELETEA(dir); DELETEA(ext); files.deletearrays(); } + + void update() + { + if((type!=FILES_DIR && type!=FILES_VAR) || millis >= commandmillis) return; + files.deletearrays(); + if(type==FILES_VAR) + { + string buf; + buf[0] = '\0'; + if(ident *id = readident(dir)) switch(id->type) + { + case ID_SVAR: copystring(buf, *id->storage.s); break; + case ID_ALIAS: copystring(buf, id->getstr()); break; + } + if(!buf[0]) copystring(buf, "."); + cleanfilesdir(buf); + listfiles(buf, ext, files); + } + else listfiles(dir, ext, files); + files.sort(); + loopv(files) if(i && !strcmp(files[i], files[i-1])) delete[] files.remove(i--); + millis = totalmillis; + } }; static inline bool htcmp(const fileskey &x, const fileskey &y) { - return x.type==y.type && !strcmp(x.dir, y.dir) && (x.ext == y.ext || (x.ext && y.ext && !strcmp(x.ext, y.ext))); + return x.type==y.type && !strcmp(x.dir, y.dir) && (x.ext == y.ext || (x.ext && y.ext && !strcmp(x.ext, y.ext))); } static inline uint hthash(const fileskey &k) { - return hthash(k.dir); + return hthash(k.dir); } static hashtable<fileskey, filesval *> completefiles; @@ -665,50 +661,50 @@ void resetcomplete() { completesize = 0; } void addcomplete(char *command, int type, char *dir, char *ext) { - if(identflags&IDF_OVERRIDDEN) - { - conoutf(CON_ERROR, "cannot override complete %s", command); - return; - } - if(!dir[0]) - { - filesval **hasfiles = completions.access(command); - if(hasfiles) *hasfiles = NULL; - return; - } - if(type==FILES_DIR) cleanfilesdir(dir); - if(ext) - { - if(strchr(ext, '*')) ext[0] = '\0'; - if(!ext[0]) ext = NULL; - } - fileskey key(type, dir, ext); - filesval **val = completefiles.access(key); - if(!val) - { - filesval *f = new filesval(type, dir, ext); - if(type==FILES_LIST) explodelist(dir, f->files); - val = &completefiles[fileskey(type, f->dir, f->ext)]; - *val = f; - } - filesval **hasfiles = completions.access(command); - if(hasfiles) *hasfiles = *val; - else completions[newstring(command)] = *val; + if(identflags&IDF_OVERRIDDEN) + { + conoutf(CON_ERROR, "cannot override complete %s", command); + return; + } + if(!dir[0]) + { + filesval **hasfiles = completions.access(command); + if(hasfiles) *hasfiles = NULL; + return; + } + if(type==FILES_DIR) cleanfilesdir(dir); + if(ext) + { + if(strchr(ext, '*')) ext[0] = '\0'; + if(!ext[0]) ext = NULL; + } + fileskey key(type, dir, ext); + filesval **val = completefiles.access(key); + if(!val) + { + filesval *f = new filesval(type, dir, ext); + if(type==FILES_LIST) explodelist(dir, f->files); + val = &completefiles[fileskey(type, f->dir, f->ext)]; + *val = f; + } + filesval **hasfiles = completions.access(command); + if(hasfiles) *hasfiles = *val; + else completions[newstring(command)] = *val; } void addfilecomplete(char *command, char *dir, char *ext) { - addcomplete(command, FILES_DIR, dir, ext); + addcomplete(command, FILES_DIR, dir, ext); } void addvarcomplete(char *command, char *var, char *ext) { - addcomplete(command, FILES_VAR, var, ext); + addcomplete(command, FILES_VAR, var, ext); } void addlistcomplete(char *command, char *list) { - addcomplete(command, FILES_LIST, list, NULL); + addcomplete(command, FILES_LIST, list, NULL); } COMMANDN(complete, addfilecomplete, "sss"); @@ -717,69 +713,69 @@ COMMANDN(listcomplete, addlistcomplete, "ss"); void complete(char *s, int maxlen, const char *cmdprefix) { - int cmdlen = 0; - if(cmdprefix) - { - cmdlen = strlen(cmdprefix); - if(strncmp(s, cmdprefix, cmdlen)) prependstring(s, cmdprefix, maxlen); - } - if(!s[cmdlen]) return; - if(!completesize) { completesize = (int)strlen(&s[cmdlen]); DELETEA(lastcomplete); } - - filesval *f = NULL; - if(completesize) - { - char *end = strchr(&s[cmdlen], ' '); - if(end) f = completions.find(stringslice(&s[cmdlen], end), NULL); - } - - const char *nextcomplete = NULL; - if(f) // complete using filenames - { - int commandsize = strchr(&s[cmdlen], ' ')+1-s; - f->update(); - loopv(f->files) - { - if(strncmp(f->files[i], &s[commandsize], completesize+cmdlen-commandsize)==0 && - (!lastcomplete || strcmp(f->files[i], lastcomplete) > 0) && (!nextcomplete || strcmp(f->files[i], nextcomplete) < 0)) - nextcomplete = f->files[i]; - } - cmdprefix = s; - cmdlen = commandsize; - } - else // complete using command names - { - enumerate(idents, ident, id, - if(strncmp(id.name, &s[cmdlen], completesize)==0 && - (!lastcomplete || strcmp(id.name, lastcomplete) > 0) && (!nextcomplete || strcmp(id.name, nextcomplete) < 0)) - nextcomplete = id.name; - ); - } - DELETEA(lastcomplete); - if(nextcomplete) - { - cmdlen = min(cmdlen, maxlen-1); - if(cmdlen) memmove(s, cmdprefix, cmdlen); - copystring(&s[cmdlen], nextcomplete, maxlen-cmdlen); - lastcomplete = newstring(nextcomplete); - } + int cmdlen = 0; + if(cmdprefix) + { + cmdlen = strlen(cmdprefix); + if(strncmp(s, cmdprefix, cmdlen)) prependstring(s, cmdprefix, maxlen); + } + if(!s[cmdlen]) return; + if(!completesize) { completesize = (int)strlen(&s[cmdlen]); DELETEA(lastcomplete); } + + filesval *f = NULL; + if(completesize) + { + char *end = strchr(&s[cmdlen], ' '); + if(end) f = completions.find(stringslice(&s[cmdlen], end), NULL); + } + + const char *nextcomplete = NULL; + if(f) // complete using filenames + { + int commandsize = strchr(&s[cmdlen], ' ')+1-s; + f->update(); + loopv(f->files) + { + if(strncmp(f->files[i], &s[commandsize], completesize+cmdlen-commandsize)==0 && + (!lastcomplete || strcmp(f->files[i], lastcomplete) > 0) && (!nextcomplete || strcmp(f->files[i], nextcomplete) < 0)) + nextcomplete = f->files[i]; + } + cmdprefix = s; + cmdlen = commandsize; + } + else // complete using command names + { + enumerate(idents, ident, id, + if(strncmp(id.name, &s[cmdlen], completesize)==0 && + (!lastcomplete || strcmp(id.name, lastcomplete) > 0) && (!nextcomplete || strcmp(id.name, nextcomplete) < 0)) + nextcomplete = id.name; + ); + } + DELETEA(lastcomplete); + if(nextcomplete) + { + cmdlen = min(cmdlen, maxlen-1); + if(cmdlen) memmove(s, cmdprefix, cmdlen); + copystring(&s[cmdlen], nextcomplete, maxlen-cmdlen); + lastcomplete = newstring(nextcomplete); + } } void writecompletions(stream *f) { - vector<char *> cmds; - enumeratekt(completions, char *, k, filesval *, v, { if(v) cmds.add(k); }); - cmds.sort(); - loopv(cmds) - { - char *k = cmds[i]; - filesval *v = completions[k]; - if(v->type==FILES_LIST) - { - if(validateblock(v->dir)) f->printf("listcomplete %s [%s]\n", escapeid(k), v->dir); - else f->printf("listcomplete %s %s\n", escapeid(k), escapestring(v->dir)); - } - else f->printf("%s %s %s %s\n", v->type==FILES_VAR ? "varcomplete" : "complete", escapeid(k), escapestring(v->dir), escapestring(v->ext ? v->ext : "*")); - } + vector<char *> cmds; + enumeratekt(completions, char *, k, filesval *, v, { if(v) cmds.add(k); }); + cmds.sort(); + loopv(cmds) + { + char *k = cmds[i]; + filesval *v = completions[k]; + if(v->type==FILES_LIST) + { + if(validateblock(v->dir)) f->printf("listcomplete %s [%s]\n", escapeid(k), v->dir); + else f->printf("listcomplete %s %s\n", escapeid(k), escapestring(v->dir)); + } + else f->printf("%s %s %s %s\n", v->type==FILES_VAR ? "varcomplete" : "complete", escapeid(k), escapestring(v->dir), escapestring(v->ext ? v->ext : "*")); + } } |
