/* Mono-Console Users: print text to the console; multi-console users use * Output() */ void OGLCONSOLE_Print(const char *s, ...) { va_list argument; char output[4096]; /* Acrue arguments in argument list */ va_start(argument, s); vsnprintf(output, 4096, s, argument); va_end(argument); /* TODO: Find some way to pass the va_list arguments to OGLCONSOLE_Output * so that we don't waste extra time with the "%s" bullshit */ OGLCONSOLE_Output((OGLCONSOLE_Console)userConsole, "%s", output); }
void cmdCB(OGLCONSOLE_Console console, char *cmd) { // TODO: Here would be a good place to use a map with member function pointers if (!strncmp(cmd, "quit", 4)) { done = true; return; } else if (!strncmp(cmd, "connect", 7)) { char address[256] = "localhost"; int port = 9999; if (sscanf(cmd, "connect %255s %i", address, &port) >= 0) { printf("connecting to %s:%i\n", address, port); OGLCONSOLE_Output(console, "connecting to %s %i\n", address, port); try { delete client; client = 0; client = new Client(address, port); OGLCONSOLE_SetVisibility(0); } catch (...) { printf("failed to connect to %s:%i\n", address, port); OGLCONSOLE_Output(console, "failed to connect to %s:%i\n", address, port); delete client; client = 0; } return; } OGLCONSOLE_Output(console, "usage: connect [address [port]]\n"); return; } else if (!strncmp(cmd, "add", 3)) { int a, b; if (sscanf(cmd, "add %i %i", &a, &b) == 2) { OGLCONSOLE_Output(console, "%i + %i = %i\n", a, b, a+b); return; } OGLCONSOLE_Output(console, "usage: add INT INT\n"); return; } else if (!strncmp(cmd, "disconnect", 10)) { delete client; client = 0; return; } OGLCONSOLE_Output(console, "I don't understand this command: %s\n", cmd); }
// Print message to console void Console::output(const char *format, ...) { #ifndef BF_NO_CONSOLE va_list args; static char message[MAX_CONSOLE_OUTPUT_LENGTH]; // Reusable buffer va_start(args, format); vsnprintf(message, sizeof(message), format, args); va_end(args); OGLCONSOLE_Output(mConsole, message); #endif }
// process an integer command static int ProcessCommandInt(int &aValue, char *aParam[], int aCount, ProcessCommandPostFunc aAction, const char *aFormat) { if (aCount >= 1) { aValue = atoi(aParam[0]); if (aAction) aAction(); return 1; } else { OGLCONSOLE_Output(console, aFormat, aValue); return 0; } }
// process a string command static int ProcessCommandString(std::string &aValue, char *aParam[], int aCount, ProcessCommandPostFunc aAction, const char *aFormat) { if (aCount >= 1) { aValue = aParam[0]; if (aAction) aAction(); return 1; } else { OGLCONSOLE_Output(console, aFormat, aValue.c_str()); return 0; } }
// process a two-integer command static int ProcessCommandInt2(int &aValue1, int &aValue2, char *aParam[], int aCount, ProcessCommandPostFunc aAction, const char *aFormat) { if (aCount >= 2) { aValue1 = atoi(aParam[0]); aValue2 = atoi(aParam[1]); if (aAction) aAction(); return 2; } else { OGLCONSOLE_Output(console, aFormat, aValue1, aValue2); return 0; } }
// commands int ProcessCommand( unsigned int aCommand, char *aParam[], int aCount ) { switch (aCommand) { case 0x11e1fc01 /* "shell" */: setgamestate = STATE_SHELL; return 0; case 0xc2cbd863 /* "play" */: setgamestate = STATE_PLAY; return 0; case 0xed7cdd8c /* "reload" */: setgamestate = STATE_RELOAD; return 0; case 0x47878736 /* "quit" */: setgamestate = STATE_QUIT; return 0; case 0x1d215c8f /* "resolution" */: return ProcessCommandInt2(SCREEN_WIDTH, SCREEN_HEIGHT, aParam, aCount, UpdateWindowAction, "resolution: %dx%d\n"); case 0xfe759eea /* "depth" */: return ProcessCommandInt(SCREEN_DEPTH, aParam, aCount, UpdateWindowAction, "depth: %dbpp"); case 0x5032fb58 /* "fullscreen" */: return ProcessCommandBool(SCREEN_FULLSCREEN, aParam, aCount, UpdateWindowAction, "fullscreen: %d\n"); case 0x06f8f066 /* "vsync" */: return ProcessCommandBool(OPENGL_SWAPCONTROL, aParam, aCount, UpdateWindowAction, "vsync: %d\n"); case 0x35c8978f /* "antialias" */: return ProcessCommandBool(OPENGL_ANTIALIAS, aParam, aCount, UpdateWindowAction, "antialias: %d\n"); case 0x47d0f228 /* "multisample" */: return ProcessCommandInt(OPENGL_MULTISAMPLE, aParam, aCount, UpdateWindowAction, "multisample: %d\n"); case 0x1ae79789 /* "viewsize" */: return ProcessCommandFloat(VIEW_SIZE, aParam, aCount, NULL, "viewsize: %f\n"); case 0xf9d86f7b /* "input" */: return ProcessCommandString(INPUT_CONFIG, aParam, aCount, InitInputAction, "input: %s\n"); case 0x9b99e7dd /* "level" */: return ProcessCommandString(LEVEL_CONFIG, aParam, aCount, InitLevelAction, "level: %s\n"); case 0x112a90d4 /* "import" */: if (aCount > 0) { // level configuration TiXmlDocument document(aParam[0]); if (!document.LoadFile()) DebugPrint("error loading import file \"%s\": %s\n", aParam[0], document.ErrorDesc()); // process child element if (const TiXmlElement *root = document.FirstChildElement()) ConfigureWorldItem(root); return 1; } return 0; case 0x87b82de3 /* "split" */: if (aCount > 0) { SplitLevel(LEVEL_CONFIG.c_str(), aParam[0]); return 1; } return 0; case 0x593058cc /* "record" */: return ProcessCommandString(RECORD_CONFIG, aParam, aCount, InitRecordAction, "record: %s\n"); case 0xcf8a43ec /* "playback" */: return ProcessCommandString(RECORD_CONFIG, aParam, aCount, InitPlaybackAction, "playback: %s\n"); case 0xd6974b06 /* "simrate" */: return ProcessCommandInt(SIMULATION_RATE, aParam, aCount, NULL, "simrate: %d\n"); case 0x9f2f269e /* "timescale" */: return ProcessCommandFloat(TIME_SCALE, aParam, aCount, NULL, "timescale: %f\n"); case 0xe065cb63 /* "fixedstep" */: return ProcessCommandBool(FIXED_STEP, aParam, aCount, NULL, "fixedstep: %d\n"); case 0xf744f3b2 /* "motionblur" */: return ProcessCommandInt(MOTIONBLUR_STEPS, aParam, aCount, ClampMotionBlurAction, "motionblur: %d\n"); case 0xfb585f73 /* "motionblurtime" */: return ProcessCommandFloat(MOTIONBLUR_TIME, aParam, aCount, NULL, "motionblurtime: %f\n"); case 0x61e734dc /* "soundchannels" */: return ProcessCommandInt(SOUND_CHANNELS, aParam, aCount, NULL, "soundchannels: %d\n"); case 0xff4838bb /* "soundvolumeeffect" */: return ProcessCommandFloat(SOUND_VOLUME_EFFECT, aParam, aCount, UpdateSoundVolume, "soundvolume: %f\n"); case 0x689fc51d /* "soundvolumemusic" */: return ProcessCommandFloat(SOUND_VOLUME_MUSIC, aParam, aCount, UpdateSoundVolume, "soundvolume: %f\n"); case 0x94c716fd /* "outputconsole" */: return ProcessCommandBool(DEBUGPRINT_OUTPUTCONSOLE, aParam, aCount, NULL, "outputconsole: %d\n"); case 0x54822903 /* "outputdebug" */: return ProcessCommandBool(DEBUGPRINT_OUTPUTDEBUG, aParam, aCount, NULL, "outputdebug: %d\n"); case 0x8940763c /* "outputstderr" */: return ProcessCommandBool(DEBUGPRINT_OUTPUTSTDERR, aParam, aCount, NULL, "outputstderr: %d\n"); case 0xfbcc8f02 /* "profilescreen" */: return ProcessCommandBool(PROFILER_OUTPUTSCREEN, aParam, aCount, NULL, "profilescreen: %d\n"); case 0x85e872f9 /* "profileprint" */: return ProcessCommandBool(PROFILER_OUTPUTPRINT, aParam, aCount, NULL, "profileprint: %d\n"); case 0x24ce5450 /* "frameratescreen" */: return ProcessCommandBool(FRAMERATE_OUTPUTSCREEN, aParam, aCount, NULL, "frameratescreen: %d\n"); case 0x55cfbc33 /* "framerateprint" */: return ProcessCommandBool(FRAMERATE_OUTPUTPRINT, aParam, aCount, NULL, "framerateprint: %d\n"); case 0xe41f87fa /* "debugdraw" */: return ProcessCommandBool(DEBUG_DRAW, aParam, aCount, NULL, "debugdraw: %d\n"); case 0xa165ddb8 /* "database" */: if (aCount >= 1) { // get the database identifier unsigned int id; if (!TIXML_SSCANF(aParam[0], "0x%x", &id)) id = Hash(aParam[0]); // get the dtabase Database::Untyped *db = Database::GetDatabases().Get(id); if (db) { // list database properties OGLCONSOLE_Output(console, "stride=%d shift=%d bits=%d limit=%d count=%d\n", db->GetStride(), db->GetShift(), db->GetBits(), db->GetLimit(), db->GetCount()); } else { // not found OGLCONSOLE_Output(console, "database \"%s\" (0x%08x) not found\n", aParam[0], id); } return 1; } else { // list all database identifiers OGLCONSOLE_Output(console, "databases:\n"); for (Database::Untyped::Iterator itor(&Database::GetDatabases()); itor.IsValid(); ++itor) { OGLCONSOLE_Output(console, "0x%08x\n", itor.GetKey()); } return 0; } case 0xbdf0855a /* "find" */: if (aCount >= 1) { // get the database identifier unsigned int id; if (!TIXML_SSCANF(aParam[0], "0x%x", &id)) id = Hash(aParam[0]); // get the database Database::Untyped *db = Database::GetDatabases().Get(id); if (db) { // if supplying a key... if (aCount >= 2) { // if the key is an identifier... unsigned int key = 0; if (TIXML_SSCANF(aParam[1], "0x%x", &key)) { // look up the identifier if (const void *value = db->Find(key)) { const std::string &name = Database::name.Get(key); OGLCONSOLE_Output(console, "name=\"%s\" key=0x%08x data=0x%p\n", name.c_str(), key, value); } else { OGLCONSOLE_Output(console, "no record found\n"); } } else { // list all keys matching the string name OGLCONSOLE_Output(console, "records matching \"%s\":\n", aParam[1]); for (Database::Untyped::Iterator itor(db); itor.IsValid(); ++itor) { const std::string &name = Database::name.Get(itor.GetKey()); if (_stricmp(name.c_str(), aParam[1]) == 0) { OGLCONSOLE_Output(console, "%d: name=\"%s\" key=0x%08x data=0x%p\n", itor.GetSlot(), name.c_str(), itor.GetKey(), itor.GetValue()); } } } return 2; } else { // list the contents of the database for (Database::Untyped::Iterator itor(db); itor.IsValid(); ++itor) { const std::string &name = Database::name.Get(itor.GetKey()); OGLCONSOLE_Output(console, "%d: name=\"%s\" key=0x%08x data=0x%p\n", itor.GetSlot(), name.c_str(), itor.GetKey(), itor.GetValue()); } } } else { // not found OGLCONSOLE_Output(console, "database \"%s\" (0x%08x) not found\n", aParam[0], id); } return 1; } else { return 0; } case 0x1bf51169 /* "components" */: if (aCount >= 1) { // get the identifier unsigned int key; if (!TIXML_SSCANF(aParam[0], "0x%x", &key)) key = Hash(aParam[0]); // for each database... for (Database::Typed<Database::Untyped *>::Iterator itor(&Database::GetDatabases()); itor.IsValid(); ++itor) { // if the database contains a record for the identifier... if (const void *value = itor.GetValue()->Find(key)) { OGLCONSOLE_Output(console, "database 0x%08x data=0x%p\n", itor.GetKey(), value); } } return 1; } else { return 0; } case 0x0e0d9594 /* "sound" */: if (aCount >= 2) { PlaySoundCue(Hash(aParam[0]), Hash(aParam[1])); return 2; } else if (aCount == 1) { PlaySoundCue(Hash(aParam[0])); return 1; } else { return 0; } default: #ifdef USE_VARIABLE // check variable system if (VarItem *item = Database::varitem.Get(aCommand)) { if (item->mType == VarItem::COMMAND) { // trigger the command item->Notify(); return 0; } else { if (aCount >= 1) { // set value item->SetString(aParam[0]); return 1; } else { // get value OGLCONSOLE_Output(console, "%s\n", item->GetString().c_str()); return 0; } } } else { return 0; } #else return 0; #endif } }
int OGLCONSOLE_SDLEvent(SDL_Event *e) { /* If the terminal is hidden we only check for show/hide key */ if (!userConsole->visible) { if (e->type == SDL_KEYDOWN && e->key.keysym.sym == '`') { // TODO: Fetch values from OS? // TODO: Expose them to the program // SDL_EnableKeyRepeat(250, 30); userConsole->visible = 1; #ifdef OGLCONSOLE_SLIDE userConsole->transitionComplete = SDL_GetTicks() + SLIDE_MS; #endif return 1; } return 0; } /* TODO: SDL_KEYPRESS? ENABLE KEY REPEAT USING THE HIDE/SHOW FUNCTION? */ if (e->type == SDL_KEYDOWN) { /* Reject most modifier keys TODO: Add some accelerator keys? */ if (e->key.keysym.mod & MOD_REJECT) return 0; /* Handle Control modifier specially */ if (e->key.keysym.mod & MOD_CTRL) { /* TODO: Add Control+Key things here */ return 0; } /* Check for hide key */ if (e->key.keysym.sym == '`') { /* Tell console to slide into closing */ userConsole->visible = 0; #ifdef OGLCONSOLE_SLIDE userConsole->transitionComplete = SDL_GetTicks() + SLIDE_MS; #endif /* Disable key repeat */ // SDL_EnableKeyRepeat(0, 0); return 1; } if (e->key.keysym.sym >= ' ' && e->key.keysym.sym <= '~') { int k = e->key.keysym.sym; char *c, *d; /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); /* Capitalize if necessary */ if (e->key.keysym.mod & MOD_CAPITALIZE) { static const int capital[] = { (int)' ', (int)'!', (int)'"', (int)'#', (int)'$', (int)'%', (int)'&', (int)'"', (int)'(', (int)')', (int)'*', (int)'+', (int)'<', (int)'_', (int)'>', (int)'?', (int)')', (int)'!', (int)'@', (int)'#', (int)'$', (int)'%', (int)'^', (int)'&', (int)'*', (int)'(', (int)':', (int)':', (int)'<', (int)'+', (int)'>', (int)'?', (int)'@', (int)'A', (int)'B', (int)'C', (int)'D', (int)'E', (int)'F', (int)'G', (int)'H', (int)'I', (int)'J', (int)'K', (int)'L', (int)'M', (int)'N', (int)'O', (int)'P', (int)'Q', (int)'R', (int)'S', (int)'T', (int)'U', (int)'V', (int)'W', (int)'X', (int)'Y', (int)'Z', (int)'{', (int)'|', (int)'}', (int)'^', (int)'_', (int)'~', (int)'A', (int)'B', (int)'C', (int)'D', (int)'E', (int)'F', (int)'G', (int)'H', (int)'I', (int)'J', (int)'K', (int)'L', (int)'M', (int)'N', (int)'O', (int)'P', (int)'Q', (int)'R', (int)'S', (int)'T', (int)'U', (int)'V', (int)'W', (int)'X', (int)'Y', (int)'Z', (int)'{', (int)'|', (int)'}', (int)'~' }; /* If we're not explicitly holding a shift key, that means just * capslock, which means we only capitalize letters */ if ((k >= 'a' && k <= 'z') || (e->key.keysym.mod & MOD_SHIFT)) k = capital[k-' ']; } /* Point to the cursor position and the end of the string */ c = userConsole->inputLine + userConsole->inputCursorPos; d = userConsole->inputLine + userConsole->inputLineLength + 1; /* Slide some of the string to the right */ for (; d != c; d--) *d = *(d-1); /* Insert new character */ *c = k; /* Increment input line length counter */ userConsole->inputLineLength++; /* Advance input cursor position */ userConsole->inputCursorPos++; return 1; } /* The operation for delete and backspace keys are very similar */ else if (e->key.keysym.sym == KEY_DELETE || e->key.keysym.sym == KEY_BACKSPACE) { char *end, *c; /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); /* Is this a backspace? */ if (e->key.keysym.sym == KEY_BACKSPACE) { /* Backspace oeprations bail if the cursor is at the beginning * of the input line */ if (userConsole->inputCursorPos == 0) return 1; /* This is all that differentiates the backspace from the delete * key */ userConsole->inputCursorPos--; } /* Delete key operations bail if the cursor is at the end of the * input line */ else if (userConsole->inputCursorPos == userConsole->inputLineLength) return 1; /* Last we shift affected text to the left, overlapping the * erased character */ c = userConsole->inputLine + userConsole->inputCursorPos; end = userConsole->inputLine + --userConsole->inputLineLength; while (c <= end) { *c = *(c+1); c++; } return 1; } else if (e->key.keysym.sym == KEY_RETURN) { /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); /* Add user's command to history */ OGLCONSOLE_AddHistory((void*)userConsole, userConsole->inputLine); /* Print user's command to the console */ OGLCONSOLE_Output((void*)userConsole, "%s\n", userConsole->inputLine); /* Invoke console's enter-key callback function */ userConsole->enterKeyCallback((void*)userConsole,userConsole->inputLine); /* Erase command line */ userConsole->inputCursorPos = 0; userConsole->inputLineLength = 0; userConsole->inputLine[0] = '\0'; return 1; } // Page up key else if (e->key.keysym.sym == KEY_PAGEUP) { userConsole->lineScrollIndex -= min(userConsole->textHeight / 2, 5); if (userConsole->lineScrollIndex < 0) userConsole->lineScrollIndex += userConsole->maxLines; printf("scroll index = %i\n", userConsole->lineScrollIndex); } // Page down key else if (e->key.keysym.sym == KEY_PAGEDOWN) { userConsole->lineScrollIndex += min(userConsole->textHeight / 2, 5); if (userConsole->lineScrollIndex >= userConsole->maxLines) userConsole->lineScrollIndex -= userConsole->maxLines; printf("scroll index = %i\n", userConsole->lineScrollIndex); } // Home key else if (e->key.keysym.sym == KEY_HOME) { /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); userConsole->inputCursorPos = 0; return 1; } // End key else if (e->key.keysym.sym == KEY_END) { /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); userConsole->inputCursorPos = userConsole->inputLineLength; return 1; } // Arrow key up else if (e->key.keysym.sym == KEY_UP) { // Shift key is for scrolling the output display if (e->key.keysym.mod & MOD_SHIFT) { if (--userConsole->lineScrollIndex < 0) userConsole->lineScrollIndex = userConsole->maxLines-1; } // No shift key is for scrolling through command history else { // -1 means we aren't look at history yet if (userConsole->historyScrollIndex == -1) { userConsole->historyScrollIndex = userConsole->historyQueueIndex; } else { // Wrap our history scrolling if (--userConsole->historyScrollIndex < 0) userConsole->historyScrollIndex = MAX_HISTORY_COUNT; } // If we've returned to our current position in the command // history, we'll just drop out of history mode if (userConsole->historyScrollIndex == userConsole->historyQueueIndex +1) userConsole->historyScrollIndex = -1; } return 1; } // Arrow key down else if (e->key.keysym.sym == KEY_DOWN) { // Shift key is for scrolling the output display if (e->key.keysym.mod & MOD_SHIFT) { if (++userConsole->lineScrollIndex >= userConsole->maxLines) userConsole->lineScrollIndex = 0; } // No shift key is for scrolling through command history else { // -1 means we aren't look at history yet if (userConsole->historyScrollIndex != -1) { // Wrap our history scrolling if (++userConsole->historyScrollIndex >= MAX_HISTORY_COUNT) userConsole->historyScrollIndex = 0; // If we've returned to our current position in the command // history, we'll just drop out of history mode if (userConsole->historyScrollIndex == userConsole->historyQueueIndex +1) userConsole->historyScrollIndex = -1; } else { // TODO: be like, no bitch, there's no history down there } } return 1; } // Arrow key left else if (e->key.keysym.sym == KEY_LEFT) { /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); if (userConsole->inputCursorPos > 0) userConsole->inputCursorPos--; return 1; } // Arrow key right else if (e->key.keysym.sym == KEY_RIGHT) { /* Yank the command history if necessary */ OGLCONSOLE_YankHistory(userConsole); if (userConsole->inputCursorPos < userConsole->inputLineLength) userConsole->inputCursorPos++; return 1; } } return 0; }
OGLCONSOLE_Console OGLCONSOLE_Create() { _OGLCONSOLE_Console *console; GLint viewport[4]; /* If font hasn't been created, we create it */ if (!glIsTexture(OGLCONSOLE_glFontHandle)) OGLCONSOLE_CreateFont(); /* Allocate memory for our console */ console = (void*)malloc(sizeof(_OGLCONSOLE_Console)); /* Textual dimensions */ glGetIntegerv(GL_VIEWPORT, viewport); console->textWidth = viewport[2] / CHAR_PIXEL_W; console->textHeight = viewport[3] / CHAR_PIXEL_H; screenWidth = (GLdouble)viewport[2] / (GLdouble)CHAR_PIXEL_W; screenHeight = (GLdouble)viewport[3] / (GLdouble)CHAR_PIXEL_H; console->characterWidth = 1.0 / floor(screenWidth); console->characterHeight = 1.0 / floor(screenHeight); /* Different values have different meanings for xMatrixUse: 0) Do not change the matrix before rendering 1) Upload the console's matrix before rendering 2) Multiply the console's matrix before rendering */ /* Initialize its projection matrix */ console->pMatrixUse = 1; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, screenWidth, 0, screenHeight, -1, 1); glGetDoublev(GL_PROJECTION_MATRIX, console->pMatrix); glPopMatrix(); /* Initialize its modelview matrix */ console->mvMatrixUse = 1; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glScaled(console->textWidth, console->textHeight, 1); glGetDoublev(GL_MODELVIEW_MATRIX, console->mvMatrix); glPopMatrix(); /* Screen and scrollback lines */ /* This is the total number of screen lines in memory (start blank) */ console->maxLines = DEFAULT_MAX_LINES; /* Allocate space for text */ console->lines = (char*)malloc(console->maxLines*(console->textWidth+1)); /* Initialize to empty strings */ memset(console->lines, 0, console->maxLines*(console->textWidth+1)); /* This variable represents whether or not a newline has been left */ console->outputNewline = 0; /* This cursor points to the X pos where console output is next destined */ console->outputCursor = console->lines; /* This cursor points to what line console output is next destined for */ console->lineQueueIndex = 0; /* This cursor points to what line the console view is scrolled to */ console->lineScrollIndex = console->maxLines - console->textHeight + 1; /* Initialize the user's input (command line) */ console->inputLineLength = 0; console->inputCursorPos = 0; console->inputLine[0] = '\0'; /* History lines */ memset(console->history, 0, MAX_INPUT_LENGTH * MAX_HISTORY_COUNT); console->historyQueueIndex = 0; console->historyScrollIndex = -1; /* Callbacks */ console->enterKeyCallback = OGLCONSOLE_DefaultEnterKeyCallback; /* The console starts life invisible */ console->visible = 0; console->transitionComplete = 0; /* If no consoles existed before, we select this one for convenience */ if (!programConsole) programConsole = console; if (!userConsole) userConsole = console; /* Temporary shit */ OGLCONSOLE_Output((void*)console, "Console initialized\n"); OGLCONSOLE_Output((void*)console, "Console display lines:\t\t%i\n", console->textHeight); OGLCONSOLE_Output((void*)console, "Console display columns:\t%i\n", console->textWidth); OGLCONSOLE_Output((void*)console, "Console input length:\t\t%i\n", MAX_INPUT_LENGTH); /* Return the opaque pointer to the programmer */ return (OGLCONSOLE_Console)console; }
static void OGLCONSOLE_DefaultEnterKeyCallback(OGLCONSOLE_Console console, char *cmd) { OGLCONSOLE_Output(console, "No enter key callback is registered for this console!\n"); }