home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / console.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-06-05  |  11.0 KB  |  380 lines

  1. // console.cpp: the console buffer, its display, and command line control
  2.  
  3. #include "cube.h"
  4.  
  5. struct cline { char *cref; int outtime; };
  6. vector<cline> conlines;
  7.  
  8. const int ndraw = 6;
  9. const int WORDWRAP = 80;
  10. int conskip = 0;
  11.  
  12. bool saycommandon = false;
  13. string commandbuf;
  14. int commandpos = -1;
  15.  
  16. void setconskip(int n)
  17. {
  18.     conskip += n;
  19.     if(conskip<0) conskip = 0;
  20. }
  21.  
  22. COMMANDN(conskip, setconskip, ARG_1INT);
  23.  
  24. void conline(const char *sf, bool highlight)        // add a line to the console buffer
  25. {
  26.     cline cl;
  27.     cl.cref = conlines.length()>100 ? conlines.pop().cref : newstringbuf("");   // constrain the buffer size
  28.     cl.outtime = lastmillis;                        // for how long to keep line on screen
  29.     conlines.insert(0,cl);
  30.     if(highlight)                                   // show line in a different colour, for chat etc.
  31.     {
  32.         cl.cref[0] = '\f';
  33.         cl.cref[1] = '0';
  34.         cl.cref[2] = 0;
  35.         s_strcat(cl.cref, sf);
  36.     }
  37.     else
  38.     {
  39.         s_strcpy(cl.cref, sf);
  40.     }
  41. }
  42.  
  43. const int CONSPAD = FONTH/3;
  44.  
  45. void conoutf(const char *s, ...)
  46. {
  47.     s_sprintfdv(sf, s);
  48.     string sp;
  49.     filtertext(sp, sf);
  50.     puts(sp);
  51.     s = sf;
  52.     vector<char *> lines;
  53.     text_block(s, VIRTW*2-2*CONSPAD-2*FONTH/3, lines);
  54.     loopv(lines) conline(lines[i], i!=0);
  55.     lines.deletecontentsa();
  56. }
  57.  
  58. bool fullconsole = false;
  59. void toggleconsole() { fullconsole = !fullconsole; }
  60. COMMAND(toggleconsole, ARG_NONE);
  61.  
  62. void rendercommand(int x, int y)
  63. {
  64.     s_sprintfd(s)("> %s", commandbuf);
  65.     int offset = text_width(s, commandpos>=0 ? commandpos+2 : -1);
  66.     blendbox(x+offset, y, x+offset+char_width(commandpos>=0 ? commandbuf[commandpos] : '_'), y+FONTH, true);
  67.     draw_text(s, x, y);
  68. }
  69.  
  70. void renderconsole()                                // render buffer taking into account time & scrolling
  71. {
  72.     if(fullconsole)
  73.     {
  74.         int w = VIRTW*2, h = VIRTH*2;
  75.         int numl = (h*2/5)/(FONTH*5/4);
  76.         int offset = min(conskip, max(conlines.length() - numl, 0));
  77.         blendbox(CONSPAD, CONSPAD, w-CONSPAD, 2*CONSPAD+numl*FONTH*5/4+2*FONTH/3, true);
  78.         loopi(numl) draw_text(offset+i>=conlines.length() ? "" : conlines[offset+i].cref, CONSPAD+FONTH/3, CONSPAD+(FONTH*5/4)*(numl-i-1)+FONTH/3);
  79.     }
  80.     else
  81.     {
  82.         int nd = 0;
  83.         char *refs[ndraw];
  84.         loopv(conlines) if(conskip ? i>=conskip-1 || i>=conlines.length()-ndraw : lastmillis-conlines[i].outtime<20000)
  85.         {
  86.             refs[nd++] = conlines[i].cref;
  87.             if(nd==ndraw) break;
  88.         }
  89.         loopj(nd) draw_text(refs[j], CONSPAD+FONTH/3, CONSPAD+(FONTH*5/4)*(nd-j-1)+FONTH/3);
  90.     }
  91. }
  92.  
  93. // keymap is defined externally in keymap.cfg
  94.  
  95. struct keym
  96. {
  97.     int code;
  98.     char *name, *action;
  99.  
  100.     ~keym() { DELETEA(name); DELETEA(action); }
  101. };
  102. vector<keym> keyms;
  103.  
  104. keym *keypressed = NULL;
  105. char *keyaction = NULL;
  106.  
  107. void keymap(char *code, char *key, char *action)
  108. {
  109.     keym &km = keyms.add();
  110.     km.code = atoi(code);
  111.     km.name = newstring(key);
  112.     km.action = newstring(action);
  113. }
  114.  
  115. COMMAND(keymap, ARG_3STR);
  116.  
  117. void bindkey(char *key, char *action)
  118. {
  119.     for(char *x = key; *x; x++) *x = toupper(*x);
  120.     loopv(keyms) if(!strcmp(keyms[i].name, key))
  121.     {
  122.         keym &km = keyms[i];
  123.         if(!keypressed || keyaction!=km.action) delete[] km.action;
  124.         km.action = newstring(action);
  125.         return;
  126.     }
  127.     conoutf("unknown key \"%s\"", key);   
  128. }
  129.  
  130. COMMANDN(bind, bindkey, ARG_2STR);
  131.  
  132. struct releaseaction
  133. {
  134.     keym *key;
  135.     char *action;
  136. };
  137. vector<releaseaction> releaseactions;
  138.  
  139. char *addreleaseaction(char *s)
  140. {
  141.     if(!keypressed) return NULL;
  142.     releaseaction &ra = releaseactions.add();
  143.     ra.key = keypressed;
  144.     ra.action = newstring(s);
  145.     return keypressed->name;
  146. }
  147.  
  148. void onrelease(char *s)
  149. {
  150.     addreleaseaction(s);
  151. }
  152.  
  153. COMMAND(onrelease, ARG_1STR);
  154.  
  155. void saycommand(char *init)                         // turns input to the command line on or off
  156. {
  157.     SDL_EnableUNICODE(saycommandon = (init!=NULL));
  158.     setscope(false);
  159.     if(!editmode) keyrepeat(saycommandon);
  160.     if(!init) init = "";
  161.     s_strcpy(commandbuf, init);
  162.     commandpos = -1;
  163.     player1->stopmoving(); // prevent situations where player presses direction key, open command line, then releases key
  164. }
  165.  
  166. void mapmsg(char *s) { s_strncpy(hdr.maptitle, s, 128); }
  167.  
  168. COMMAND(saycommand, ARG_VARI);
  169. COMMAND(mapmsg, ARG_1STR);
  170.  
  171. #if !defined(WIN32) && !defined(__APPLE__)
  172. #include <X11/Xlib.h>
  173. #include <SDL_syswm.h>
  174. #endif
  175.  
  176. void pasteconsole()
  177. {
  178.     #ifdef WIN32
  179.     if(!IsClipboardFormatAvailable(CF_TEXT)) return; 
  180.     if(!OpenClipboard(NULL)) return;
  181.     char *cb = (char *)GlobalLock(GetClipboardData(CF_TEXT));
  182.     s_strcat(commandbuf, cb);
  183.     GlobalUnlock(cb);
  184.     CloseClipboard();
  185.     #elif defined(__APPLE__)
  186.     extern void mac_pasteconsole(char *commandbuf);
  187.     
  188.     mac_pasteconsole(commandbuf);
  189.     #else
  190.     SDL_SysWMinfo wminfo;
  191.     SDL_VERSION(&wminfo.version); 
  192.     wminfo.subsystem = SDL_SYSWM_X11;
  193.     if(!SDL_GetWMInfo(&wminfo)) return;
  194.     int cbsize;
  195.     char *cb = XFetchBytes(wminfo.info.x11.display, &cbsize);
  196.     if(!cb || !cbsize) return;
  197.     int commandlen = strlen(commandbuf);
  198.     for(char *cbline = cb, *cbend; commandlen + 1 < _MAXDEFSTR && cbline < &cb[cbsize]; cbline = cbend + 1)
  199.     {
  200.         cbend = (char *)memchr(cbline, '\0', &cb[cbsize] - cbline);
  201.         if(!cbend) cbend = &cb[cbsize];
  202.         if(commandlen + cbend - cbline + 1 > _MAXDEFSTR) cbend = cbline + _MAXDEFSTR - commandlen - 1;
  203.         memcpy(&commandbuf[commandlen], cbline, cbend - cbline);
  204.         commandlen += cbend - cbline;
  205.         commandbuf[commandlen] = '\n';
  206.         if(commandlen + 1 < _MAXDEFSTR && cbend < &cb[cbsize]) ++commandlen;
  207.         commandbuf[commandlen] = '\0';
  208.     }
  209.     XFree(cb);
  210.     #endif
  211. }
  212.  
  213. cvector vhistory;
  214. int histpos = 0;
  215.  
  216. void history(int n)
  217. {
  218.     static bool rec = false;
  219.     if(!rec && n>=0 && n<vhistory.length())
  220.     {
  221.         rec = true;
  222.         execute(vhistory[vhistory.length()-n-1]);
  223.         rec = false;
  224.     }
  225. }
  226.  
  227. COMMAND(history, ARG_1INT);
  228.  
  229. void keypress(int code, bool isdown, int cooked)
  230. {
  231.     if(saycommandon)                                // keystrokes go to commandline
  232.     {
  233.         if(isdown)
  234.         {
  235.             switch(code)
  236.             {
  237.                 case SDLK_RETURN:
  238.                 case SDLK_KP_ENTER:
  239.                     break;
  240.  
  241.                 case SDLK_DELETE:
  242.                 {
  243.                     int len = (int)strlen(commandbuf);
  244.                     if(commandpos<0) break;
  245.                     memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos);
  246.                     resetcomplete();
  247.                     if(commandpos>=len-1) commandpos = -1;
  248.                     break;
  249.                 }
  250.  
  251.                 case SDLK_BACKSPACE:
  252.                 {
  253.                     int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len;
  254.                     if(i<1) break;
  255.                     memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1);
  256.                     resetcomplete();
  257.                     if(commandpos>0) commandpos--;
  258.                     else if(!commandpos && len<=1) commandpos = -1;
  259.                     break;
  260.                 }
  261.  
  262.                 case SDLK_LEFT:
  263.                     if(commandpos>0) commandpos--;
  264.                     else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1;
  265.                     break;
  266.  
  267.                 case SDLK_RIGHT:
  268.                     if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1;
  269.                     break;
  270.  
  271.                 case SDLK_UP:
  272.                     if(histpos) s_strcpy(commandbuf, vhistory[--histpos]);
  273.                     break;
  274.  
  275.                 case SDLK_DOWN:
  276.                     if(histpos<vhistory.length()) s_strcpy(commandbuf, vhistory[histpos++]);
  277.                     break;
  278.  
  279.                 case SDLK_TAB:
  280.                     complete(commandbuf);
  281.                     if(commandpos>=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1;
  282.                     break;
  283.  
  284.                 case SDLK_F1:
  285.                     toggledoc();
  286.                     break;
  287.  
  288.                 case SDLK_F2:
  289.                     scrolldoc(-4);
  290.                     break;
  291.  
  292.                 case SDLK_F3:
  293.                     scrolldoc(4);
  294.                     break;
  295.  
  296.                 case SDLK_v:
  297.                     if(SDL_GetModState()&(KMOD_LCTRL|KMOD_RCTRL)) { pasteconsole(); return; }
  298.  
  299.                 default:
  300.                     resetcomplete();
  301.                     if(cooked)
  302.                     {
  303.                         size_t len = (int)strlen(commandbuf);
  304.                         if(len+1<sizeof(commandbuf))
  305.                         {
  306.                             if(commandpos<0) commandbuf[len] = cooked;
  307.                             else
  308.                             {
  309.                                 memmove(&commandbuf[commandpos+1], &commandbuf[commandpos], len - commandpos);
  310.                                 commandbuf[commandpos++] = cooked;
  311.                             }
  312.                             commandbuf[len+1] = '\0';
  313.                         }
  314.                     }
  315.             }
  316.         }
  317.         else
  318.         {
  319.             if(code==SDLK_RETURN)
  320.             {
  321.                 if(commandbuf[0])
  322.                 {
  323.                     if(vhistory.empty() || strcmp(vhistory.last(), commandbuf))
  324.                     {
  325.                         vhistory.add(newstring(commandbuf));  // cap this?
  326.                     }
  327.                     histpos = vhistory.length();
  328.                     if(commandbuf[0]=='/') execute(commandbuf);
  329.                     else toserver(commandbuf);
  330.                 }
  331.                 saycommand(NULL);
  332.             }
  333.             else if(code==SDLK_ESCAPE)
  334.             {
  335.                 saycommand(NULL);
  336.             }
  337.         }
  338.     }
  339.     else if(!menukey(code, isdown))                 // keystrokes go to menu
  340.     {
  341.         loopv(keyms) if(keyms[i].code==code)        // keystrokes go to game, lookup in keymap and execute
  342.         {
  343.             keym &k = keyms[i];
  344.             loopv(releaseactions)
  345.             {
  346.                 releaseaction &ra = releaseactions[i];
  347.                 if(ra.key==&k)
  348.                 {
  349.                     if(!isdown) execute(ra.action);
  350.                     delete[] ra.action;
  351.                     releaseactions.remove(i--);
  352.                 }
  353.             }
  354.             if(isdown)
  355.             {
  356.                 keyaction = k.action;
  357.                 keypressed = &k;
  358.                 execute(keyaction);
  359.                 keypressed = NULL;
  360.                 if(keyaction!=k.action) delete[] keyaction;
  361.             }
  362.             break;
  363.         }
  364.     }
  365. }
  366.  
  367. char *getcurcommand()
  368. {
  369.     return saycommandon ? commandbuf : NULL;
  370. }
  371.  
  372. void writebinds(FILE *f)
  373. {
  374.     loopv(keyms)
  375.     {
  376.         if(*keyms[i].action) fprintf(f, "bind \"%s\" [%s]\n",     keyms[i].name, keyms[i].action);
  377.     }
  378. }
  379.  
  380.