123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643 |
- /* GCSx
- ** DEBUG.CPP
- **
- ** Debugging functions, including console I/O
- */
- /*****************************************************************************
- ** Copyright (C) 2003-2006 Janson
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation; either version 2 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program; if not, write to the Free Software
- ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
- *****************************************************************************/
- #include "all.h"
- // Debug level
- int currentDebugLevel = 0;
- int debugLevel(int newLevel) {
- if (newLevel >= 0) currentDebugLevel = newLevel;
- return currentDebugLevel;
- }
- // Debugging console
- DebugWin* debug = NULL;
- list<string>* debugText = NULL;
- int inExitStage = 0;
- char* dwBuffer = NULL;
- int DebugWin::wantsToBeDeleted() const { start_func
- return 0;
- }
- DebugWin::DebugWin() : EditBox(debugText, FONT_MONO, 1), commandHistory() { start_func
- commandHistoryPosition = 0;
- newCommand = 1;
- }
- DebugWin::~DebugWin() { start_func
- }
- void DebugWin::selectAllConsole() { start_func
- cursorToStart(0);
- cursorToEnd(1);
- }
- void DebugWin::cursorToStart(int drag) { start_func
- TextPoint point;
- findDLine(dNumLines - 1, &point.vRow);
- point.column = CONSOLE_LENGTH;
- insertionState(point, drag);
- }
- void DebugWin::cursorToEnd(int drag) { start_func
- TextPoint point;
- point.vRow = vNumLines - 1;
- point.column = (*findVLine(vNumLines - 1)).length;
- insertionState(point, drag);
- }
- // Typing-related events handled like a console
- int DebugWin::event(int hasFocus, const SDL_Event* event) { start_func
- string clipStorage;
- TextPoint point;
- list<string>::iterator pointLine;
- int onLastLine = 0;
- int onLastLineInitial = 0;
- VLine* vl = &*findVLine(insertion.vRow);
- if ((vl->dLine == dNumLines - 1) && (vl->colStart + insertion.column >= CONSOLE_LENGTH)) {
- if (vl->colStart + insertion.column == CONSOLE_LENGTH) onLastLineInitial = 1;
- onLastLine = 1;
- }
- if (isSelect) {
- vl = &*findVLine(selectBegin.vRow);
- if ((vl->dLine < dNumLines - 1) || (vl->colStart + selectBegin.column < CONSOLE_LENGTH)) onLastLine = 0;
- }
-
- // Readonly unless solely on last line
- if (onLastLine) readonly = 0;
- switch (event->type) {
- case SDL_COMMAND:
- switch (event->user.code) {
- case EDIT_PASTE:
- // Only allow pasting single line text
- if (!canConvertClipboard(CLIPBOARD_TEXT_LINE)) readonly = 1;
- break;
- case EDIT_SELECTALL:
- selectAllConsole();
- return 1;
- }
- break;
- case SDL_KEYDOWN: {
- int drag = 0;
- Sint32 key;
- if (event->key.keysym.mod & KMOD_SHIFT) {
- drag = 1; // We'll check this if we care about SHIFT
- key = combineKey(event->key.keysym.sym, event->key.keysym.mod & ~KMOD_SHIFT);
- }
- else {
- key = combineKey(event->key.keysym.sym, event->key.keysym.mod);
- }
-
- switch (key) {
- case SDLK_BACKSPACE:
- // Disallow if first character of console line and no selection
- if ((onLastLineInitial) && (!isSelect)) readonly = 1;
- break;
-
- case SDLK_DOWN:
- case SDLK_UP:
- // Manage command history
- if (onLastLine) {
- // Get cmd
- point = insertion;
- vl = &*findVLine(point.vRow);
- string cmd = (*vl->dLineI).substr(CONSOLE_LENGTH, string::npos);
- // Only spaces?
- string::size_type pos = 0;
- pos = cmd.find_first_not_of(' ', pos);
- // (only spaces present?)
- if (pos != string::npos) {
- // Add to command history
- if ((newCommand) || (commandHistoryPosition >= commandHistory.size())) {
- if (commandHistoryPosition >= commandHistory.size()) {
- // So adding cmd to end of history will allow us to "down" to a blank line
- newCommand = 0;
- commandHistoryPosition = commandHistory.size();
- }
- commandHistory.push_back(cmd);
- if (commandHistory.size() > MAX_COMMAND_HISTORY) {
- commandHistory.erase(commandHistory.begin());
- --commandHistoryPosition;
- }
- }
- // Update existing command
- else if (cmd != commandHistory[commandHistoryPosition]) {
- commandHistory[commandHistoryPosition] = cmd;
- }
- }
- else if (commandHistoryPosition > commandHistory.size()) {
- commandHistoryPosition = commandHistory.size();
- }
-
- if (key == SDLK_DOWN) {
- // If was a new command, we don't move as we didn't
- // insert that command right where we are
- if (!newCommand) {
- if (++commandHistoryPosition > commandHistory.size()) {
- commandHistoryPosition = commandHistory.size();
- }
- }
- }
- else {
- if (commandHistoryPosition > 0) {
- --commandHistoryPosition;
- }
- }
-
- // Show new command
- selectAllConsole();
- if (commandHistoryPosition >= commandHistory.size()) {
- pasteText(blankString);
- newCommand = 1;
- }
- else {
- pasteText(commandHistory[commandHistoryPosition]);
- newCommand = 0;
- }
-
- return 1;
- }
- break;
- case SDLK_LEFT:
- // Disallow if first character of console line
- if (onLastLineInitial) return 1;
- break;
- case SDLK_HOME:
- case combineKey(SDLK_HOME, KMOD_CTRL):
- if (onLastLine) {
- cursorToStart(drag);
- return 1;
- }
- break;
- case SDLK_PAGEUP:
- if (myFrame) {
- myFrame->scrollBy(0, max(1, (viewHeight / lineHeight) - 1) * lineHeight);
- }
- if (myScroll) {
- myScroll->scrollBy(0, max(1, (viewHeight / lineHeight) - 1) * lineHeight);
- }
- return 1;
- case SDLK_PAGEDOWN:
- if (myFrame) {
- myFrame->scrollBy(0, max(1, (viewHeight / lineHeight) - 1) * -lineHeight);
- }
- if (myScroll) {
- myScroll->scrollBy(0, max(1, (viewHeight / lineHeight) - 1) * -lineHeight);
- }
- return 1;
- case combineKey(SDLK_LEFT, KMOD_CTRL):
- // Disallow if first character of console line
- if (onLastLineInitial) return 1;
- break;
- case SDLK_TAB:
- // @TODO: command completion
- return 1;
-
- case SDLK_RETURN:
- case SDLK_KP_ENTER:
- if (onLastLine) {
- // Get cmd
- point = insertion;
- vl = &*findVLine(point.vRow);
- string cmd = (*vl->dLineI).substr(CONSOLE_LENGTH, string::npos);
- // Only spaces?
- string::size_type pos = 0;
- pos = cmd.find_first_not_of(' ', pos);
- // (only spaces present?)
- if (pos != string::npos) {
- // Add to command history
- if ((newCommand) || (commandHistoryPosition >= commandHistory.size())) {
- commandHistory.push_back(cmd);
- if (commandHistory.size() > MAX_COMMAND_HISTORY) {
- commandHistory.erase(commandHistory.begin());
- }
- commandHistoryPosition = commandHistory.size();
- }
- // Update existing history
- else {
- if (cmd != commandHistory[commandHistoryPosition]) {
- commandHistory[commandHistoryPosition] = cmd;
- }
- // After this, "up" should put us at the same command
- ++commandHistoryPosition;
- }
- }
-
- // Add new prompt
- cursorToEnd();
- pasteText("\n");
- pasteText(CONSOLE_PROMPT);
- newCommand = 1;
- // Process cmd
- consoleParse(cmd);
- return 1;
- }
- break;
-
- default:
- // Special-case to ignore default VIEW_CONSOLE shortcut key
- if (key == config->readShortcut(VIEW_CONSOLE)) return 0;
- break;
- }
- break;
- }
- }
-
- int result = EditBox::event(hasFocus, event);
- readonly = 1;
- return result;
- }
- void DebugWin::updateTitlebar() { start_func
- if (myFrame) {
- myFrame->setTitle("Console");
- }
- }
- void DebugWin::prepOpen() { start_func
- EditBox::prepOpen();
- // Move cursor to end
- cursorToEnd();
- }
- void DebugWin::paintText(const string& text, const string& entireLine, int posInLine, int x, int y, SDL_Surface* destSurface, int isSelected) const { start_func
- if (strcmp(CONSOLE_PROMPT, entireLine.substr(0, CONSOLE_LENGTH).c_str())) {
- drawText(text, guiRGB[isSelected ? COLOR_TEXTBOX : COLOR_TEXT], x, y, destSurface, font);
- }
- else {
- if (posInLine < CONSOLE_LENGTH) {
- drawText(text.substr(0, CONSOLE_LENGTH - posInLine), guiRGB[isSelected ? COLOR_TEXTBOX : COLOR_CONSOLEPROMPT], x, y, destSurface, font);
- if (text.size() > (string::size_type)(CONSOLE_LENGTH - posInLine)) {
- x += fontWidth(text.substr(0, CONSOLE_LENGTH - posInLine), font);
- drawText(text.substr(CONSOLE_LENGTH - posInLine, string::npos), guiRGB[isSelected ? COLOR_TEXTBOX : COLOR_CONSOLEINPUT], x, y, destSurface, font);
- }
- }
- else {
- drawText(text, guiRGB[isSelected ? COLOR_TEXTBOX : COLOR_CONSOLEINPUT], x, y, destSurface, font);
- }
- }
- }
- void DebugWin::addLine(const char* text) { start_func
- VLine* vl = &*findDLine(dNumLines - 1);
- debugText->insert(vl->dLineI, text);
- contentInsert(dNumLines - 1, 1);
- }
- void initDebugBuffer() { start_func
- if (!debugText) {
- debugText = new list<string>;
- // Console prompt
- debugText->push_back(CONSOLE_PROMPT);
- }
- if (!dwBuffer) dwBuffer = new char[DEBUG_BUFFER_SIZE];
- }
- void initDebugWindow() { start_func
- if (!debug) {
- debug = new DebugWin();
- debug->init();
- }
- }
- void beginExitStage() { start_func
- inExitStage = 1;
- }
- void exitDebug() { start_func
- delete debug;
- delete[] dwBuffer;
- delete debugText;
- debug = NULL;
- dwBuffer = NULL;
- debugText = NULL;
- }
- DebugWin* debugWindow() { start_func
- return debug;
- }
- int inDebug = 0;
- void debugClear() { start_func
- inDebug = 1;
-
- if (debug) {
- debug->selectAll();
- debug->pasteText(CONSOLE_PROMPT);
- }
- else if (debugText) {
- debugText->clear();
- debugText->push_back(CONSOLE_PROMPT);
- }
-
- inDebug = 0;
- }
- void debugStdout(const char* text, va_list& args) {
- if (stdout) {
- vfprintf(stdout, text, args);
- fputc('\n', stdout);
- fflush(stdout);
- }
- }
- void debugWrite(const char* text, va_list& args) {
- assert(text);
-
- if (inDebug) return;
- inDebug = 1;
-
- if (inExitStage) {
- debugStdout(text, args);
- }
- else {
- if (!dwBuffer) dwBuffer = new char[DEBUG_BUFFER_SIZE];
- vsnprintf(dwBuffer, DEBUG_BUFFER_SIZE, text, args);
- dwBuffer[DEBUG_BUFFER_SIZE - 1] = 0;
- if (stdout) {
- fwrite(dwBuffer, 1, strlen(dwBuffer), stdout);
- fputc('\n', stdout);
- fflush(stdout);
- }
- if (debug) {
- debug->addLine(dwBuffer);
- }
- else if (debugText) {
- // Insert before console prompt
- list<string>::iterator pos = debugText->end();
- --pos;
- debugText->insert(pos, dwBuffer);
- }
- }
- inDebug = 0;
- }
- void debugStdout(const char* text, ...) {
- va_list arglist;
- va_start(arglist, text);
- debugStdout(text, arglist);
- va_end(arglist);
- }
- void debugWrite(const char* text, ...) {
- if (inDebug) return;
-
- va_list arglist;
- va_start(arglist, text);
- debugWrite(text, arglist);
- va_end(arglist);
- }
- void debugStdout(int level, const char* text, ...) {
- if ((level) && (!(currentDebugLevel & level))) return;
- va_list arglist;
- va_start(arglist, text);
- debugStdout(text, arglist);
- va_end(arglist);
- }
- void debugWrite(int level, const char* text, ...) {
- if (inDebug) return;
- if ((level) && (!(currentDebugLevel & level))) return;
- va_list arglist;
- va_start(arglist, text);
- debugWrite(text, arglist);
- va_end(arglist);
- }
- void debugDump(const void* data, int size, int toStdOut) {
- if (inDebug) return;
-
- if (!data) {
- if (toStdOut) debugStdout("<NULL>");
- else debugWrite("<NULL>");
- return;
- }
-
- string output;
- const Uint8* data8 = (Uint8*)data;
-
- while (size) {
- output = "";
- for (int pos = 0; (pos < 48) && (size); ++pos, --size, ++data8) {
- if (((pos % 4) == 0) && (pos)) output += " ";
-
- int nib = (*data8) >> 4;
- if (nib < 10) output += '0' + nib;
- else output += 'A' - 10 + nib;
- nib = (*data8) & 0xF;
- if (nib < 10) output += '0' + nib;
- else output += 'A' - 10 + nib;
- }
-
- if (toStdOut) debugStdout(output.c_str());
- else debugWrite(output.c_str());
- }
- }
- // Other stuff
- const string errorTitleInvalidEntry("Invalid Entry");
- const string errorTitleVideo("Video Error");
- const string errorTitleException("Internal Exception");
- const string errorTitleImageOverflow("Image Memory Overflow");
- const string errorTitleResourceLoad("Resource Loading Error");
- const string errorTitleFile("File Error");
- const string errorTitleImport("Import Error");
- const string errorTitleDuplicateName("Duplicate Name");
- const string errorTitleMissingName("Missing Name");
- const string errorTitleInUse("Resource In Use");
- const string warnTitleReminder("Reminder");
- const string messageBoxYes("\tYes");
- const string messageBoxNo("\tNo");
- const string messageBoxOK("OK");
- const string messageBoxCancel("Cancel");
- const string messageBoxReminder("\tDon't show this warning again");
- #if defined(WIN32)
- #include <windows.h>
- void systemErrorBox(const char* text, const char* title) {
- assert(text);
- debugWrite(DEBUG_FATALERROR, text);
- if (title == NULL) {
- MessageBoxA(NULL, text, "An Error Has Occurred", 16);
- }
- else {
- MessageBoxA(NULL, text, title, 16);
- }
- }
- #else
- void systemErrorBox(const char* text, const char* title) {
- debugWrite(DEBUG_FATALERROR, text);
- }
- #endif
- int guiRemindBox(const std::string& text, const std::string& title) { start_func
- Dialog* d = NULL;
- Widget* w = NULL;
- d = new Dialog(title);
- w = new WStatic(0, text);
- w->addTo(d);
- int checked = 0;
- w = new WCheckBox(0, messageBoxReminder, &checked, 1);
- w->addTo(d);
- w = new WButton(0, messageBoxOK, Dialog::BUTTON_OK);
- w->addTo(d);
- d->makePretty(1);
- d->runModal();
- delete d;
- return checked;
- }
- void guiErrorBox(const string& text, const string& title) { start_func
- Dialog* d = NULL;
- Widget* w = NULL;
-
- d = new Dialog(title);
- w = new WStatic(0, text);
- w->addTo(d);
- w = new WButton(0, messageBoxOK, Dialog::BUTTON_OK);
- w->addTo(d);
-
- d->makePretty();
- d->runModal();
- delete d;
- }
- int guiConfirmBox(const string& text, const string& title) { start_func
- Dialog* d = NULL;
- Widget* w = NULL;
- int result = 0;
-
- d = new Dialog(title);
- w = new WStatic(0, text);
- w->addTo(d);
- w = new WButton(1, messageBoxOK, Dialog::BUTTON_OK);
- w->addTo(d);
-
- w = new WButton(0, messageBoxCancel, Dialog::BUTTON_CANCEL);
- w->addTo(d);
-
- d->makePretty();
- result = d->runModal();
- delete d;
- return result;
- }
- int guiMessageBox(const string& text, const string& title, const string* buttonA, const string* buttonB, const string* buttonC, const string* buttonD, const string* buttonE) { start_func
- Dialog* d = NULL;
- Widget* w = NULL;
- int result = 0;
-
- d = new Dialog(title);
- w = new WStatic(0, text);
- w->addTo(d);
- if (buttonA) {
- w = new WButton(1, *buttonA, Dialog::BUTTON_OK);
- w->addTo(d);
- }
-
- if (buttonB) {
- w = new WButton(2, *buttonB, Dialog::BUTTON_OK);
- w->addTo(d);
- }
-
- if (buttonC) {
- w = new WButton(3, *buttonC, Dialog::BUTTON_OK);
- w->addTo(d);
- }
-
- if (buttonD) {
- w = new WButton(4, *buttonD, Dialog::BUTTON_OK);
- w->addTo(d);
- }
-
- if (buttonE) {
- w = new WButton(5, *buttonE, Dialog::BUTTON_OK);
- w->addTo(d);
- }
-
- d->makePretty();
- result = d->runModal();
- delete d;
- return result;
- }
|