summaryrefslogtreecommitdiff
path: root/src/engine/console.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/console.cpp')
-rw-r--r--src/engine/console.cpp1110
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 : "*"));
+ }
}