2 * Code for controlling the console
3 * Based on an old version of SDL_Console
5 * Written By: Garrett Banuk <mongoose@mongeese.org>
6 * Code Cleanup and heavily extended by: Clemens Wacha <reflex-2000@gmx.net>
7 * Ported to use native Descent interfaces by: Bradley Bell <btb@icculus.org>
9 * This is free, just be sure to give us credit when using it
10 * in any of your programs.
40 int text_console_enabled = 1;
43 #define text_console_enabled (!isvga())
47 /* Console specific cvars */
48 /* How discriminating we are about which messages are displayed */
49 cvar_t con_threshold = {"con_threshold", "0",};
51 /* Private console stuff */
52 #define CON_NUM_LINES 40
54 #define FG_COLOR grd_curcanv->cv_font_fg_color
55 #define get_msecs() approx_fsec_to_msec(timer_get_approx_seconds())
57 #define CON_BG_HIRES (cfexist("scoresb.pcx")?"scoresb.pcx":"scores.pcx")
58 #define CON_BG_LORES (cfexist("scores.pcx")?"scores.pcx":"scoresb.pcx") // Mac datafiles only have scoresb.pcx
59 #define CON_BG ((SWIDTH>=640)?CON_BG_HIRES:CON_BG_LORES)
63 static ConsoleInformation Console;
64 #define console (&Console)
66 /* console is ready to be written to */
67 static int con_initialized;
71 void CON_UpdateOffset(void);
72 /*! Frees all the memory loaded by the console */
75 /*! Sets the alpha channel of an SDL_Surface to the specified value (0 - transparend,
76 255 - opaque). Use this function also for OpenGL. */
77 void CON_Alpha(unsigned char alpha);
78 /*! Internal: Sets the alpha channel of an SDL_Surface to the specified value.
79 Preconditions: the surface in question is RGBA. 0 <= a <= 255, where 0 is transparent and 255 opaque */
80 void CON_AlphaGL(SDL_Surface *s, int alpha);
81 /*! Sets a background image for the console */
83 int CON_Background(grs_bitmap *image);
84 /*! Sets font info for the console */
85 void CON_Font(grs_font *font, int fg, int bg);
86 /*! Modify the prompt of the console */
87 void CON_SetPrompt(char* newprompt);
88 /*! Set the key, that invokes a CON_Hide() after press. default is ESCAPE and you can always hide using
89 ESCAPE and the HideKey. compared against event->key.keysym.sym !! */
90 void CON_SetHideKey(int key);
91 /*! Internal: executes the command typed in at the console (called if you press ENTER)*/
92 void CON_Execute(char* command);
93 /*! Internal: Gets called when TAB was pressed */
94 void CON_TabCompletion(void);
95 /*! Internal: makes newline (same as printf("\n") or CON_Out("\n") ) */
96 void CON_NewLineConsole(void);
97 /*! Internal: shift command history (the one you can switch with the up/down keys) */
98 void CON_NewLineCommand(void);
99 /*! Internal: updates console after resize etc. */
100 void CON_UpdateConsole(void);
103 /*! Internal: draws the commandline the user is typing in to the screen. called by update? */
104 void DrawCommandLine();
106 /*! Internal: Gets called if you press the LEFT key (move cursor left) */
107 void Cursor_Left(void);
108 /*! Internal: Gets called if you press the RIGHT key (move cursor right) */
109 void Cursor_Right(void);
110 /*! Internal: Gets called if you press the HOME key (move cursor to the beginning
112 void Cursor_Home(void);
113 /*! Internal: Gets called if you press the END key (move cursor to the end of the line*/
114 void Cursor_End(void);
115 /*! Internal: Called if you press DELETE (deletes character under the cursor) */
116 void Cursor_Del(void);
117 /*! Internal: Called if you press BACKSPACE (deletes character left of cursor) */
118 void Cursor_BSpace(void);
119 /*! Internal: Called if you type in a character (add the char to the command) */
120 void Cursor_Add(int event);
122 /*! Internal: Called if you press Ctrl-C (deletes the commandline) */
123 void Clear_Command(void);
124 /*! Internal: Called if you press Ctrl-L (deletes the History) */
125 void Clear_History(void);
127 /*! Internal: Called if you press UP key (switches through recent typed in commands */
128 void Command_Up(void);
129 /*! Internal: Called if you press DOWN key (switches through recent typed in commands */
130 void Command_Down(void);
133 /* Takes keys from the keyboard and inputs them to the console
134 If the event was not handled (i.e. WM events or unknown ctrl-shift
135 sequences) the function returns the event for further processing. */
136 int CON_Events(int event)
141 if(event & KEY_CTRLED)
144 switch(event & ~KEY_CTRLED)
163 else if(event & KEY_ALTED)
165 //the console does not handle ALT combinations!
170 //first of all, check if the console hide key was pressed
171 if(event == console->HideKey)
176 switch (event & 0xff)
182 if(event & KEY_SHIFTED)
184 console->ConsoleScrollBack = console->LineBuffer-1;
191 if(event & KEY_SHIFTED)
193 console->ConsoleScrollBack = 0;
200 console->ConsoleScrollBack += CON_LINE_SCROLL;
201 if(console->ConsoleScrollBack > console->LineBuffer-1)
202 console->ConsoleScrollBack = console->LineBuffer-1;
207 console->ConsoleScrollBack -= CON_LINE_SCROLL;
208 if(console->ConsoleScrollBack < 0)
209 console->ConsoleScrollBack = 0;
231 console->InsMode = 1-console->InsMode;
237 if(strlen(console->Command) > 0) {
238 CON_NewLineCommand();
240 // copy the input into the past commands strings
241 strcpy(console->CommandLines[0], console->Command);
243 // display the command including the prompt
244 CON_Out("%s%s", console->Prompt, console->Command);
247 CON_Execute(console->Command);
250 console->CommandScrollBack = -1;
258 if (key_to_ascii(event) == 255)
272 /* CON_AlphaGL() -- sets the alpha channel of an SDL_Surface to the
273 * specified value. Preconditions: the surface in question is RGBA.
274 * 0 <= a <= 255, where 0 is transparent and 255 is opaque. */
275 void CON_AlphaGL(SDL_Surface *s, int alpha) {
280 SDL_PixelFormat *format;
281 static char errorPrinted = 0;
284 /* debugging assertions -- these slow you down, but hey, crashing sucks */
286 PRINT_ERROR("NULL Surface passed to CON_AlphaGL\n");
290 /* clamp alpha value to 0...255 */
291 if(alpha < SDL_ALPHA_TRANSPARENT)
292 val = SDL_ALPHA_TRANSPARENT;
293 else if(alpha > SDL_ALPHA_OPAQUE)
294 val = SDL_ALPHA_OPAQUE;
298 /* loop over alpha channels of each pixel, setting them appropriately. */
302 switch (format->BytesPerPixel) {
304 /* 16-bit surfaces don't seem to support alpha channels. */
307 PRINT_ERROR("16-bit SDL surfaces do not support alpha-blending under OpenGL.\n");
311 /* we can do this very quickly in 32-bit mode. 24-bit is more
312 * difficult. And since 24-bit mode is reall the same as 32-bit,
313 * so it usually ends up taking this route too. Win! Unroll loop
314 * and use pointer arithmetic for extra speed. */
315 int numpixels = h * (w << 2);
316 Uint8 *pix = (Uint8 *) (s->pixels);
317 Uint8 *last = pix + numpixels;
319 if((numpixels & 0x7) == 0)
320 for(pixel = pix + 3; pixel < last; pixel += 32)
321 *pixel = *(pixel + 4) = *(pixel + 8) = *(pixel + 12) = *(pixel + 16) = *(pixel + 20) = *(pixel + 24) = *(pixel + 28) = val;
323 for(pixel = pix + 3; pixel < last; pixel += 4)
328 /* we have no choice but to do this slowly. <sigh> */
329 for(y = 0; y < h; ++y)
330 for(x = 0; x < w; ++x) {
332 /* Lock the surface for direct access to the pixels */
333 if(SDL_MUSTLOCK(s) && SDL_LockSurface(s) < 0) {
334 PRINT_ERROR("Can't lock surface: ");
335 fprintf(stderr, "%s\n", SDL_GetError());
338 pixel = DT_GetPixel(s, x, y);
341 SDL_GetRGBA(pixel, format, &r, &g, &b, &a);
342 pixel = SDL_MapRGBA(format, r, g, b, val);
343 SDL_GetRGBA(pixel, format, &r, &g, &b, &a);
344 DT_PutPixel(s, x, y, pixel);
346 /* unlock surface again */
348 SDL_UnlockSurface(s);
356 /* Updates the console buffer */
357 void CON_UpdateConsole(void) {
361 grs_canvas *canv_save;
364 /* Due to the Blits, the update is not very fast: So only update if it's worth it */
368 Screenlines = console->ConsoleSurface->cv_h / (CON_LINE_SPACE + console->ConsoleSurface->cv_font->ft_h);
370 canv_save = grd_curcanv;
371 gr_set_current_canvas(console->ConsoleSurface);
374 SDL_FillRect(console->ConsoleSurface, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, console->ConsoleAlpha));
380 if(grd_curscreen->flags & SDL_OPENGLBLIT)
381 SDL_SetAlpha(console->ConsoleSurface, 0, SDL_ALPHA_OPAQUE);
384 /* draw the background image if there is one */
385 if(console->BackgroundImage)
386 gr_bitmap(0, 0, console->BackgroundImage);
388 /* Draw the text from the back buffers, calculate in the scrollback from the user
389 * this is a normal SDL software-mode blit, so we need to temporarily set the ColorKey
390 * for the font, and then clear it when we're done.
393 if((grd_curscreen->flags & SDL_OPENGLBLIT) && (grd_curscreen->format->BytesPerPixel > 2)) {
394 Uint32 *pix = (Uint32 *) (CurrentFont->FontSurface->pixels);
395 SDL_SetColorKey(CurrentFont->FontSurface, SDL_SRCCOLORKEY, *pix);
399 //now draw text from last but second line to top
400 for(loop = 0; loop < Screenlines-1 && loop < console->LineBuffer - console->ConsoleScrollBack; loop++) {
401 if(console->ConsoleScrollBack != 0 && loop == 0)
402 for(loop2 = 0; loop2 < (console->VChars / 5) + 1; loop2++)
404 orig_color = FG_COLOR;
405 gr_string(CON_CHAR_BORDER + (loop2*5*console->ConsoleSurface->cv_font->ft_w), (Screenlines - loop - 2) * (CON_LINE_SPACE + console->ConsoleSurface->cv_font->ft_h), CON_SCROLL_INDICATOR);
406 FG_COLOR = orig_color;
410 orig_color = FG_COLOR;
411 gr_string(CON_CHAR_BORDER, (Screenlines - loop - 2) * (CON_LINE_SPACE + console->ConsoleSurface->cv_font->ft_h), console->ConsoleLines[console->ConsoleScrollBack + loop]);
412 FG_COLOR = orig_color;
416 gr_set_current_canvas(canv_save);
419 if(grd_curscreen->flags & SDL_OPENGLBLIT)
420 SDL_SetColorKey(CurrentFont->FontSurface, 0, 0);
424 void CON_UpdateOffset(void) {
425 switch(console->Visible) {
427 console->RaiseOffset -= CON_OPENCLOSE_SPEED;
428 if(console->RaiseOffset <= 0) {
429 console->RaiseOffset = 0;
430 console->Visible = CON_CLOSED;
434 console->RaiseOffset += CON_OPENCLOSE_SPEED;
435 if(console->RaiseOffset >= console->ConsoleSurface->cv_h) {
436 console->RaiseOffset = console->ConsoleSurface->cv_h;
437 console->Visible = CON_OPEN;
446 /* Draws the console buffer to the screen if the console is "visible" */
447 void CON_DrawConsole(void) {
448 grs_canvas *canv_save;
451 /* only draw if console is visible: here this means, that the console is not CON_CLOSED */
452 if(console->Visible == CON_CLOSED)
455 /* Update the scrolling offset */
458 /* Update the command line since it has a blinking cursor */
462 /* before drawing, make sure the alpha channel of the console surface is set
463 * properly. (sigh) I wish we didn't have to do this every frame... */
464 if(grd_curscreen->flags & SDL_OPENGLBLIT)
465 CON_AlphaGL(console->ConsoleSurface, console->ConsoleAlpha);
468 canv_save = grd_curcanv;
469 gr_set_current_canvas(&grd_curscreen->sc_canvas);
471 clip = gr_create_sub_bitmap(&console->ConsoleSurface->cv_bitmap, 0, console->ConsoleSurface->cv_h - console->RaiseOffset, console->ConsoleSurface->cv_w, console->RaiseOffset);
473 gr_bitmap(0, 0, clip);
474 gr_free_sub_bitmap(clip);
477 if(grd_curscreen->flags & SDL_OPENGLBLIT)
478 SDL_UpdateRects(grd_curscreen, 1, &DestRect);
481 gr_set_current_canvas(canv_save);
485 /* Initializes the console */
490 console->Visible = CON_CLOSED;
491 console->RaiseOffset = 0;
492 console->ConsoleLines = NULL;
493 console->CommandLines = NULL;
494 console->TotalConsoleLines = 0;
495 console->ConsoleScrollBack = 0;
496 console->TotalCommands = 0;
497 console->BackgroundImage = NULL;
499 console->ConsoleAlpha = SDL_ALPHA_OPAQUE;
502 console->InsMode = 1;
503 console->CursorPos = 0;
504 console->CommandScrollBack = 0;
505 console->Prompt = CON_DEFAULT_PROMPT;
506 console->HideKey = CON_DEFAULT_HIDEKEY;
508 /* load the console surface */
509 console->ConsoleSurface = NULL;
511 /* Load the dirty rectangle for user input */
512 console->InputBackground = NULL;
514 console->VChars = CON_CHARS_PER_LINE - 1;
515 console->LineBuffer = CON_NUM_LINES;
517 console->ConsoleLines = (char **)d_malloc(sizeof(char *) * console->LineBuffer);
518 console->CommandLines = (char **)d_malloc(sizeof(char *) * console->LineBuffer);
519 for(loop = 0; loop <= console->LineBuffer - 1; loop++) {
520 console->ConsoleLines[loop] = (char *)d_calloc(CON_CHARS_PER_LINE, sizeof(char));
521 console->CommandLines[loop] = (char *)d_calloc(CON_CHARS_PER_LINE, sizeof(char));
523 memset(console->Command, 0, CON_CHARS_PER_LINE);
524 memset(console->LCommand, 0, CON_CHARS_PER_LINE);
525 memset(console->RCommand, 0, CON_CHARS_PER_LINE);
526 memset(console->VCommand, 0, CON_CHARS_PER_LINE);
530 /* Initialise the cvars */
531 cvar_registervariable (&con_threshold);
539 void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline);
540 void CON_InitGFX(int w, int h)
546 if (console->ConsoleSurface) {
547 /* resize console surface */
548 gr_free_bitmap_data(&console->ConsoleSurface->cv_bitmap);
549 gr_init_bitmap_alloc(&console->ConsoleSurface->cv_bitmap, BM_LINEAR, 0, 0, w, h, w);
551 /* load the console surface */
552 console->ConsoleSurface = gr_create_canvas(w, h);
555 /* Load the consoles font */
556 CON_Font(SMALL_FONT, gr_getcolor(63,63,63), -1);
558 /* make sure that the size of the console is valid */
559 if(w > grd_curscreen->sc_w || w < console->ConsoleSurface->cv_font->ft_w * 32)
560 w = grd_curscreen->sc_w;
561 if(h > grd_curscreen->sc_h || h < console->ConsoleSurface->cv_font->ft_h)
562 h = grd_curscreen->sc_h;
564 /* Load the dirty rectangle for user input */
565 if (console->InputBackground)
566 gr_free_bitmap(console->InputBackground);
567 console->InputBackground = gr_create_bitmap(w, console->ConsoleSurface->cv_font->ft_h);
569 SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE));
572 /* calculate the number of visible characters in the command line */
573 console->VChars = (w - CON_CHAR_BORDER) / console->ConsoleSurface->cv_font->ft_w;
574 if(console->VChars >= CON_CHARS_PER_LINE)
575 console->VChars = CON_CHARS_PER_LINE - 1;
577 gr_init_bitmap_data(&bmp);
578 pcx_error = pcx_read_bitmap(CON_BG, &bmp, BM_LINEAR, pal);
579 Assert(pcx_error == PCX_ERROR_NONE);
580 gr_remap_bitmap_good(&bmp, pal, -1, -1);
581 CON_Background(&bmp);
582 gr_free_bitmap_data(&bmp);
586 /* Makes the console visible */
587 void CON_Show(void) {
588 console->Visible = CON_OPENING;
592 /* Hides the console (make it invisible) */
593 void CON_Hide(void) {
594 console->Visible = CON_CLOSING;
597 /* tells wether the console is visible or not */
598 int CON_isVisible(void) {
599 return((console->Visible == CON_OPEN) || (console->Visible == CON_OPENING));
602 /* Frees all the memory loaded by the console */
603 void CON_Free(void) {
606 for(i = 0; i <= console->LineBuffer - 1; i++) {
607 d_free(console->ConsoleLines[i]);
608 d_free(console->CommandLines[i]);
610 d_free(console->ConsoleLines);
611 d_free(console->CommandLines);
613 console->ConsoleLines = NULL;
614 console->CommandLines = NULL;
616 gr_free_canvas(console->ConsoleSurface);
617 console->ConsoleSurface = NULL;
619 if (console->BackgroundImage)
620 gr_free_bitmap(console->BackgroundImage);
621 console->BackgroundImage = NULL;
623 gr_free_bitmap(console->InputBackground);
624 console->InputBackground = NULL;
630 /* Increments the console lines */
631 void CON_NewLineConsole(void) {
635 temp = console->ConsoleLines[console->LineBuffer - 1];
637 for(loop = console->LineBuffer - 1; loop > 0; loop--)
638 console->ConsoleLines[loop] = console->ConsoleLines[loop - 1];
640 console->ConsoleLines[0] = temp;
642 memset(console->ConsoleLines[0], 0, CON_CHARS_PER_LINE);
643 if(console->TotalConsoleLines < console->LineBuffer - 1)
644 console->TotalConsoleLines++;
646 //Now adjust the ConsoleScrollBack
647 //dont scroll if not at bottom
648 if(console->ConsoleScrollBack != 0)
649 console->ConsoleScrollBack++;
651 if(console->ConsoleScrollBack > console->LineBuffer-1)
652 console->ConsoleScrollBack = console->LineBuffer-1;
657 /* Increments the command lines */
658 void CON_NewLineCommand(void) {
662 temp = console->CommandLines[console->LineBuffer - 1];
665 for(loop = console->LineBuffer - 1; loop > 0; loop--)
666 console->CommandLines[loop] = console->CommandLines[loop - 1];
668 console->CommandLines[0] = temp;
670 memset(console->CommandLines[0], 0, CON_CHARS_PER_LINE);
671 if(console->TotalCommands < console->LineBuffer - 1)
672 console->TotalCommands++;
675 /* Draws the command line the user is typing in to the screen */
676 /* completely rewritten by C.Wacha */
677 void DrawCommandLine() {
681 grs_font* CurrentFont;
683 static unsigned int LastBlinkTime = 0; /* Last time the consoles cursor blinked */
684 static int LastCursorPos = 0; // Last Cursor Position
685 static int Blink = 0; /* Is the cursor currently blinking */
686 grs_canvas *canv_save;
689 commandbuffer = console->VChars - strlen(console->Prompt)-1; // -1 to make cursor visible
692 CurrentFont = console->ConsoleSurface->cv_font;
695 //Concatenate the left and right side to command
696 strcpy(console->Command, console->LCommand);
697 strncat(console->Command, console->RCommand, strlen(console->RCommand));
699 //calculate display offset from current cursor position
700 if(console->Offset < console->CursorPos - commandbuffer)
701 console->Offset = console->CursorPos - commandbuffer;
702 if(console->Offset > console->CursorPos)
703 console->Offset = console->CursorPos;
705 //first add prompt to visible part
706 strcpy(console->VCommand, console->Prompt);
708 //then add the visible part of the command
709 strncat(console->VCommand, &console->Command[console->Offset], strlen(&console->Command[console->Offset]));
711 //now display the result
714 //once again we're drawing text, so in OpenGL context we need to temporarily set up
715 //software-mode transparency.
716 if(grd_curscreen->flags & SDL_OPENGLBLIT) {
717 Uint32 *pix = (Uint32 *) (CurrentFont->FontSurface->pixels);
718 SDL_SetColorKey(CurrentFont->FontSurface, SDL_SRCCOLORKEY, *pix);
722 canv_save = grd_curcanv;
723 gr_set_current_canvas(console->ConsoleSurface);
725 //first of all restore InputBackground
726 gr_bitmap(0, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, console->InputBackground);
729 orig_color = FG_COLOR;
730 gr_string(CON_CHAR_BORDER, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, console->VCommand);
731 FG_COLOR = orig_color;
733 //at last add the cursor
734 //check if the blink period is over
735 if(get_msecs() > LastBlinkTime) {
736 LastBlinkTime = get_msecs() + CON_BLINK_RATE;
743 //check if cursor has moved - if yes display cursor anyway
744 if(console->CursorPos != LastCursorPos) {
745 LastCursorPos = console->CursorPos;
746 LastBlinkTime = get_msecs() + CON_BLINK_RATE;
751 int prompt_width, cmd_width, h, w;
753 gr_get_string_size(console->Prompt, &prompt_width, &h, &w);
754 gr_get_string_size(console->LCommand + console->Offset, &cmd_width, &h, &w);
755 x = CON_CHAR_BORDER + prompt_width + cmd_width;
756 orig_color = FG_COLOR;
758 gr_string(x, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, CON_INS_CURSOR);
760 gr_string(x, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, CON_OVR_CURSOR);
761 FG_COLOR = orig_color;
764 gr_set_current_canvas(canv_save);
768 if(grd_curscreen->flags & SDL_OPENGLBLIT) {
769 SDL_SetColorKey(CurrentFont->FontSurface, 0, 0);
775 # define vsnprintf _vsnprintf
778 /* Outputs text to the console (in game), up to CON_CHARS_PER_LINE chars can be entered */
779 void CON_Out(const char *str, ...) {
781 //keep some space free for stuff like CON_Out("blablabla %s", console->Command);
782 char temp[CON_CHARS_PER_LINE + 128];
785 va_start(marker, str);
786 vsnprintf(temp, CON_CHARS_PER_LINE + 127, str, marker);
791 //temp now contains the complete string we want to output
792 // the only problem is that temp is maybe longer than the console
793 // width so we have to cut it into several pieces
795 if(console->ConsoleLines) {
796 while(strlen(ptemp) > console->VChars) {
797 CON_NewLineConsole();
798 strncpy(console->ConsoleLines[0], ptemp, console->VChars);
799 console->ConsoleLines[0][console->VChars] = '\0';
800 ptemp = &ptemp[console->VChars];
802 CON_NewLineConsole();
803 strncpy(console->ConsoleLines[0], ptemp, console->VChars);
804 console->ConsoleLines[0][console->VChars] = '\0';
811 /* Sets the alpha level of the console, 0 turns off alpha blending */
812 void CON_Alpha(unsigned char alpha) {
813 /* store alpha as state! */
814 console->ConsoleAlpha = alpha;
816 if((grd_curscreen->flags & SDL_OPENGLBLIT) == 0) {
818 SDL_SetAlpha(console->ConsoleSurface, 0, alpha);
820 SDL_SetAlpha(console->ConsoleSurface, SDL_SRCALPHA, alpha);
823 // CON_UpdateConsole();
828 /* Adds background image to the console, scaled to size of console*/
829 int CON_Background(grs_bitmap *image)
831 /* Free the background from the console */
833 if (console->BackgroundImage)
834 gr_free_bitmap(console->BackgroundImage);
835 console->BackgroundImage = NULL;
837 SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE));
842 /* Load a new background */
843 if (console->BackgroundImage)
844 gr_free_bitmap(console->BackgroundImage);
845 console->BackgroundImage = gr_create_bitmap(console->ConsoleSurface->cv_w, console->ConsoleSurface->cv_h);
846 gr_bitmap_scale_to(image, console->BackgroundImage);
849 SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE));
851 gr_bm_bitblt(console->BackgroundImage->bm_w, console->InputBackground->bm_h, 0, 0, 0, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, console->BackgroundImage, console->InputBackground);
856 /* Sets font info for the console */
857 void CON_Font(grs_font *font, int fg, int bg)
859 grs_canvas *canv_save;
861 canv_save = grd_curcanv;
862 gr_set_current_canvas(console->ConsoleSurface);
863 gr_set_curfont(font);
864 gr_set_fontcolor(fg, bg);
865 gr_set_current_canvas(canv_save);
868 void gr_init_bitmap_alloc( grs_bitmap *bm, int mode, int x, int y, int w, int h, int bytesperline);
869 /* resizes the console, has to reset alot of stuff
870 * returns 1 on error */
871 void CON_Resize(int w, int h)
873 /* make sure that the size of the console is valid */
874 if(w > grd_curscreen->sc_w || w < console->ConsoleSurface->cv_font->ft_w * 32)
875 w = grd_curscreen->sc_w;
876 if(h > grd_curscreen->sc_h || h < console->ConsoleSurface->cv_font->ft_h)
877 h = grd_curscreen->sc_h;
879 /* resize console surface */
880 gr_free_bitmap_data(&console->ConsoleSurface->cv_bitmap);
881 gr_init_bitmap_alloc(&console->ConsoleSurface->cv_bitmap, BM_LINEAR, 0, 0, w, h, w);
883 /* Load the dirty rectangle for user input */
884 gr_free_bitmap(console->InputBackground);
885 console->InputBackground = gr_create_bitmap(w, console->ConsoleSurface->cv_font->ft_h);
887 /* Now reset some stuff dependent on the previous size */
888 console->ConsoleScrollBack = 0;
890 /* Reload the background image (for the input text area) in the console */
891 if(console->BackgroundImage) {
893 SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE));
895 gr_bm_bitblt(console->BackgroundImage->bm_w, console->InputBackground->bm_h, 0, 0, 0, console->ConsoleSurface->cv_h - console->ConsoleSurface->cv_font->ft_h, console->BackgroundImage, console->InputBackground);
899 /* restore the alpha level */
900 CON_Alpha(console->ConsoleAlpha);
904 /* Sets the Prompt for console */
905 void CON_SetPrompt(char* newprompt) {
906 //check length so we can still see at least 1 char :-)
907 if(strlen(newprompt) < console->VChars)
908 console->Prompt = d_strdup(newprompt);
910 CON_Out("prompt too long. (max. %i chars)", console->VChars - 1);
913 /* Sets the key that deactivates (hides) the console. */
914 void CON_SetHideKey(int key) {
915 console->HideKey = key;
918 /* Executes the command entered */
919 void CON_Execute(char* command) {
923 void CON_TabCompletion(void) {
927 command = d_strdup(console->LCommand);
928 command = cmd_complete(command);
931 return; //no tab completion took place so return silently
934 if(j > CON_CHARS_PER_LINE - 2)
935 j = CON_CHARS_PER_LINE-1;
937 memset(console->LCommand, 0, CON_CHARS_PER_LINE);
938 console->CursorPos = 0;
940 for(i = 0; i < j; i++) {
941 console->CursorPos++;
942 console->LCommand[i] = command[i];
944 //add a trailing space
945 console->CursorPos++;
946 console->LCommand[j] = ' ';
947 console->LCommand[j+1] = '\0';
950 void Cursor_Left(void) {
951 char temp[CON_CHARS_PER_LINE];
953 if(console->CursorPos > 0) {
954 console->CursorPos--;
955 strcpy(temp, console->RCommand);
956 strcpy(console->RCommand, &console->LCommand[strlen(console->LCommand)-1]);
957 strcat(console->RCommand, temp);
958 console->LCommand[strlen(console->LCommand)-1] = '\0';
959 //CON_Out("L:%s, R:%s", console->LCommand, console->RCommand);
963 void Cursor_Right(void) {
964 char temp[CON_CHARS_PER_LINE];
966 if(console->CursorPos < strlen(console->Command)) {
967 console->CursorPos++;
968 strncat(console->LCommand, console->RCommand, 1);
969 strcpy(temp, console->RCommand);
970 strcpy(console->RCommand, &temp[1]);
971 //CON_Out("L:%s, R:%s", console->LCommand, console->RCommand);
975 void Cursor_Home(void) {
976 char temp[CON_CHARS_PER_LINE];
978 console->CursorPos = 0;
979 strcpy(temp, console->RCommand);
980 strcpy(console->RCommand, console->LCommand);
981 strncat(console->RCommand, temp, strlen(temp));
982 memset(console->LCommand, 0, CON_CHARS_PER_LINE);
985 void Cursor_End(void) {
986 console->CursorPos = strlen(console->Command);
987 strncat(console->LCommand, console->RCommand, strlen(console->RCommand));
988 memset(console->RCommand, 0, CON_CHARS_PER_LINE);
991 void Cursor_Del(void) {
992 char temp[CON_CHARS_PER_LINE];
994 if(strlen(console->RCommand) > 0) {
995 strcpy(temp, console->RCommand);
996 strcpy(console->RCommand, &temp[1]);
1000 void Cursor_BSpace(void) {
1001 if(console->CursorPos > 0) {
1002 console->CursorPos--;
1004 if(console->Offset < 0)
1005 console->Offset = 0;
1006 console->LCommand[strlen(console->LCommand)-1] = '\0';
1010 void Cursor_Add(int event)
1012 if(strlen(console->Command) < CON_CHARS_PER_LINE - 1)
1014 console->CursorPos++;
1015 console->LCommand[strlen(console->LCommand)] = key_to_ascii(event);
1016 console->LCommand[strlen(console->LCommand)] = '\0';
1020 void Clear_Command(void) {
1021 console->CursorPos = 0;
1022 memset(console->VCommand, 0, CON_CHARS_PER_LINE);
1023 memset(console->Command, 0, CON_CHARS_PER_LINE);
1024 memset(console->LCommand, 0, CON_CHARS_PER_LINE);
1025 memset(console->RCommand, 0, CON_CHARS_PER_LINE);
1028 void Clear_History(void) {
1031 for(loop = 0; loop <= console->LineBuffer - 1; loop++)
1032 memset(console->ConsoleLines[loop], 0, CON_CHARS_PER_LINE);
1035 void Command_Up(void) {
1036 if(console->CommandScrollBack < console->TotalCommands - 1) {
1037 /* move back a line in the command strings and copy the command to the current input string */
1038 console->CommandScrollBack++;
1039 memset(console->RCommand, 0, CON_CHARS_PER_LINE);
1040 console->Offset = 0;
1041 strcpy(console->LCommand, console->CommandLines[console->CommandScrollBack]);
1042 console->CursorPos = strlen(console->CommandLines[console->CommandScrollBack]);
1043 CON_UpdateConsole();
1047 void Command_Down(void) {
1048 if(console->CommandScrollBack > -1) {
1049 /* move forward a line in the command strings and copy the command to the current input string */
1050 console->CommandScrollBack--;
1051 memset(console->RCommand, 0, CON_CHARS_PER_LINE);
1052 memset(console->LCommand, 0, CON_CHARS_PER_LINE);
1053 console->Offset = 0;
1054 if(console->CommandScrollBack > -1)
1055 strcpy(console->LCommand, console->CommandLines[console->CommandScrollBack]);
1056 console->CursorPos = strlen(console->LCommand);
1057 CON_UpdateConsole();
1061 /* Print a message to the console */
1062 void con_printf(int priority, char *fmt, ...)
1067 if (priority <= ((int)con_threshold.value))
1069 va_start (arglist, fmt);
1070 vsprintf (buffer, fmt, arglist);
1073 if (con_initialized)
1076 if (text_console_enabled)
1078 /* Produce a sanitised version and send it to the standard output */
1097 printf("%s", buffer);