// console.cpp: the console buffer, its display, and command line control #include "cube.h" #include struct cline { char *cref; int outtime; }; vector conlines; const int ndraw = 5; const int WORDWRAP = 80; int conskip = 0; bool saycommandon = false; string commandbuf; void setconskip(int n) { conskip += n; if(conskip<0) conskip = 0; }; COMMANDN(conskip, setconskip, ARG_1INT); void conline(const char *sf, bool highlight) // add a line to the console buffer { cline cl; cl.cref = conlines.length()>100 ? conlines.pop().cref : newstringbuf(""); // constrain the buffer size cl.outtime = lastmillis; // for how long to keep line on screen conlines.insert(0,cl); if(highlight) // show line in a different colour, for chat etc. { cl.cref[0] = '\f'; cl.cref[1] = 0; strcat_s(cl.cref, sf); } else { strcpy_s(cl.cref, sf); }; puts(cl.cref); #ifndef WIN32 fflush(stdout); #endif }; void conoutf(const char *s, ...) { sprintf_sdv(sf, s); s = sf; int n = 0; while(strlen(s)>WORDWRAP) // cut strings to fit on screen { string t; strn0cpy(t, s, WORDWRAP+1); conline(t, n++!=0); s += WORDWRAP; }; conline(s, n!=0); }; void renderconsole() // render buffer taking into account time & scrolling { int nd = 0; char *refs[ndraw]; loopv(conlines) if(conskip ? i>=conskip-1 || i>=conlines.length()-ndraw : lastmillis-conlines[i].outtime<20000) { refs[nd++] = conlines[i].cref; if(nd==ndraw) break; }; loopj(nd) { draw_text(refs[j], FONTH/3, (FONTH/4*5)*(nd-j-1)+FONTH/3, 2); }; }; // keymap is defined externally in keymap.cfg struct keym { int code; char *name; char *action; } keyms[256]; int numkm = 0; void keymap(char *code, char *key, char *action) { keyms[numkm].code = atoi(code); keyms[numkm].name = newstring(key); keyms[numkm++].action = newstringbuf(action); }; COMMAND(keymap, ARG_3STR); void bindkey(char *key, char *action) { for(char *x = key; *x; x++) *x = toupper(*x); loopi(numkm) if(strcmp(keyms[i].name, key)==0) { strcpy_s(keyms[i].action, action); return; }; conoutf("unknown key \"%s\"", key); }; COMMANDN(bind, bindkey, ARG_2STR); void saycommand(char *init) // turns input to the command line on or off { SDL_EnableUNICODE(saycommandon = (init!=NULL)); if(!editmode) keyrepeat(saycommandon); if(!init) init = ""; strcpy_s(commandbuf, init); }; void mapmsg(char *s) { strn0cpy(hdr.maptitle, s, 128); }; COMMAND(saycommand, ARG_VARI); COMMAND(mapmsg, ARG_1STR); #ifndef WIN32 #include #include #endif void pasteconsole() { #ifdef WIN32 if(!IsClipboardFormatAvailable(CF_TEXT)) return; if(!OpenClipboard(NULL)) return; char *cb = (char *)GlobalLock(GetClipboardData(CF_TEXT)); strcat_s(commandbuf, cb); GlobalUnlock(cb); CloseClipboard(); #else SDL_SysWMinfo wminfo; SDL_VERSION(&wminfo.version); wminfo.subsystem = SDL_SYSWM_X11; if(!SDL_GetWMInfo(&wminfo)) return; int cbsize; char *cb = XFetchBytes(wminfo.info.x11.display, &cbsize); if(!cb || !cbsize) return; int commandlen = strlen(commandbuf); for(char *cbline = cb, *cbend; commandlen + 1 < _MAXDEFSTR && cbline < &cb[cbsize]; cbline = cbend + 1) { cbend = (char *)memchr(cbline, '\0', &cb[cbsize] - cbline); if(!cbend) cbend = &cb[cbsize]; if(commandlen + cbend - cbline + 1 > _MAXDEFSTR) cbend = cbline + _MAXDEFSTR - commandlen - 1; memcpy(&commandbuf[commandlen], cbline, cbend - cbline); commandlen += cbend - cbline; commandbuf[commandlen] = '\n'; if(commandlen + 1 < _MAXDEFSTR && cbend < &cb[cbsize]) ++commandlen; commandbuf[commandlen] = '\0'; }; XFree(cb); #endif }; cvector vhistory; int histpos = 0; void history(int n) { static bool rec = false; if(!rec && n>=0 && n