Quellcode durchsuchen

Console working.

Added quit command. Fixed bug in bufferString segfaulting with too big strings.
Thomas Buck vor 11 Jahren
Ursprung
Commit
5a7d335545
5 geänderte Dateien mit 158 neuen und 28 gelöschten Zeilen
  1. 9
    0
      include/Console.h
  2. 116
    2
      src/Console.cpp
  3. 21
    19
      src/OpenRaider.cpp
  4. 2
    2
      src/main.cpp
  5. 10
    5
      src/utils/strings.cpp

+ 9
- 0
include/Console.h Datei anzeigen

@@ -8,6 +8,9 @@
8 8
 #ifndef _CONSOLE_H_
9 9
 #define _CONSOLE_H_
10 10
 
11
+#include <cstring>
12
+#include <vector>
13
+
11 14
 #include "Window.h"
12 15
 
13 16
 /*!
@@ -30,6 +33,8 @@ public:
30 33
 
31 34
     bool isVisible();
32 35
 
36
+    void print(const char *s, ...) __attribute__((format(printf, 2, 3)));
37
+
33 38
     void display();
34 39
 
35 40
     void handleKeyboard(KeyboardButton key, bool pressed);
@@ -39,6 +44,10 @@ public:
39 44
 private:
40 45
 
41 46
     bool mVisible;
47
+    char *mInputBuffer;
48
+    size_t mInputBufferPointer;
49
+    char *mPartialInput;
50
+    std::vector<char *> mHistory;
42 51
 };
43 52
 
44 53
 #endif

+ 116
- 2
src/Console.cpp Datei anzeigen

@@ -16,13 +16,32 @@
16 16
 #include "config.h"
17 17
 #include "Console.h"
18 18
 #include "main.h"
19
+#include "utils/strings.h"
19 20
 #include "utils/time.h"
20 21
 
22
+#define INPUT_BUFFER_SIZE 255
23
+
21 24
 Console::Console() {
22 25
     mVisible = false;
26
+    mInputBuffer = new char[INPUT_BUFFER_SIZE + 1];
27
+    mInputBuffer[INPUT_BUFFER_SIZE] = '\0';
28
+    mInputBufferPointer = 0;
29
+    mPartialInput = NULL;
23 30
 }
24 31
 
25 32
 Console::~Console() {
33
+    if (mInputBuffer)
34
+        delete [] mInputBuffer;
35
+
36
+    if (mPartialInput)
37
+        delete [] mPartialInput;
38
+
39
+    while (mHistory.size() > 0) {
40
+        char *tmp = mHistory.back();
41
+        if (tmp != NULL)
42
+            delete [] tmp;
43
+        mHistory.pop_back();
44
+    }
26 45
 }
27 46
 
28 47
 void Console::setVisible(bool visible) {
@@ -34,28 +53,123 @@ bool Console::isVisible() {
34 53
     return mVisible;
35 54
 }
36 55
 
56
+void Console::print(const char *s, ...) {
57
+    va_list args;
58
+    va_start(args, s);
59
+    char *tmp = bufferString(s, args);
60
+    va_end(args);
61
+
62
+    if (tmp != NULL) {
63
+        mHistory.push_back(tmp);
64
+        printf("%s\n", tmp);
65
+    }
66
+}
67
+
37 68
 void Console::display() {
38 69
     Window *window = gOpenRaider->mWindow;
39 70
     unsigned char color[4] = {0xFF, 0xFF, 0xFF, 0xFF};
40 71
 
41 72
     if (mVisible) {
73
+        // Calculate line drawing geometry
74
+        // Depends on window height, so recalculate every time
75
+        unsigned int firstLine = 35;
76
+        unsigned int lastLine = (window->mHeight / 2) - 55;
77
+        unsigned int inputLine = (window->mHeight / 2) - 30;
78
+        unsigned int lineSteps = 20;
79
+        unsigned int lineCount = (lastLine - firstLine + lineSteps) / lineSteps;
80
+        while (((lineCount * lineSteps) + firstLine) < inputLine) {
81
+            lineSteps++;
82
+            lineCount = (lastLine - firstLine + lineSteps) / lineSteps;
83
+        }
84
+
42 85
         // Draw half-transparent *overlay*
43 86
         glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
44 87
         glDisable(GL_TEXTURE_2D);
45 88
         glRecti(0, 0, window->mWidth, window->mHeight / 2);
46 89
         glEnable(GL_TEXTURE_2D);
47 90
 
48
-        gOpenRaider->mWindow->drawText(10, 10, 0.50f, color, "%lus uptime %s", systemTimerGet() / 1000, VERSION);
91
+        gOpenRaider->mWindow->drawText(10, 10, 0.70f, color, "%s uptime %lus", VERSION, systemTimerGet() / 1000);
92
+
93
+        // Draw output log
94
+        int end = lineCount;
95
+        int drawOffset = 0;
96
+        int historyOffset = 0;
97
+        if (mHistory.size() < lineCount) {
98
+            end = mHistory.size();
99
+            drawOffset = lineCount - mHistory.size();
100
+        } else if (lineCount < mHistory.size()) {
101
+            historyOffset = mHistory.size() - lineCount;
102
+        }
103
+        for (int i = 0; i < end; i++) {
104
+            gOpenRaider->mWindow->drawText(10, ((i + drawOffset) * lineSteps) + firstLine,
105
+                    0.75f, color, "%s", mHistory[i + historyOffset]);
106
+        }
107
+
108
+        // Draw current input
109
+        if ((mInputBufferPointer > 0) && (mInputBuffer[0] != '\0')) {
110
+            gOpenRaider->mWindow->drawText(10, inputLine, 0.75f, color, "> %s", mInputBuffer);
111
+        } else {
112
+            gOpenRaider->mWindow->drawText(10, inputLine, 0.75f, color, ">");
113
+        }
114
+
115
+        //! \todo display the current mPartialInput. The UTF-8 segfaults SDL-TTF, somehow?
49 116
     }
50 117
 }
51 118
 
52 119
 void Console::handleKeyboard(KeyboardButton key, bool pressed) {
53 120
     if (pressed && (key == enter)) {
121
+        // Execute entered command
122
+        if ((mInputBufferPointer > 0) && (mInputBuffer[0] != '\0')) {
123
+            mHistory.push_back(bufferString("> %s", mInputBuffer));
124
+            gOpenRaider->command(mInputBuffer);
125
+        }
126
+
127
+        // Clear partial and input buffer
128
+        mInputBufferPointer = 0;
129
+        mInputBuffer[0] = '\0';
130
+        if (mPartialInput != NULL) {
131
+            delete [] mPartialInput;
132
+            mPartialInput = NULL;
133
+        }
134
+    }
54 135
 
136
+    //! \fixme only deleting the last byte is not valid for non-ASCII UTF-8 strings
137
+    if (pressed && (key == backspace)) {
138
+        if (mInputBufferPointer > 0) {
139
+            mInputBufferPointer--;
140
+            mInputBuffer[mInputBufferPointer] = '\0';
141
+        }
55 142
     }
56 143
 }
57 144
 
58 145
 void Console::handleText(char *text, bool notFinished) {
59
-    printf("Got %s (%s)\n", text, (notFinished ? "not finished" : "finished"));
146
+    //printf("Text: %s (%s)\n", text, (notFinished ? "not finished" : "finished"));
147
+
148
+    if (!notFinished) {
149
+        // Finished entering character
150
+        // delete previous partial character, if present
151
+        if (mPartialInput != NULL) {
152
+            delete [] mPartialInput;
153
+        }
154
+
155
+        //! \fixme Temporary hack filtering the console activation key
156
+        if (text[0] == '`')
157
+            return;
158
+
159
+        // Append new input to buffer
160
+        size_t length = strlen(text);
161
+        if (length > 0) {
162
+            if (((INPUT_BUFFER_SIZE - mInputBufferPointer) < length)) {
163
+                printf("Console input buffer overflowed! (> %d)\n", INPUT_BUFFER_SIZE);
164
+                return;
165
+            }
166
+            strcpy((mInputBuffer + mInputBufferPointer), text);
167
+            mInputBufferPointer += length;
168
+            mInputBuffer[mInputBufferPointer] = '\0';
169
+        }
170
+    } else {
171
+        // Partial character received
172
+        mPartialInput = bufferString("%s", text);
173
+    }
60 174
 }
61 175
 

+ 21
- 19
src/OpenRaider.cpp Datei anzeigen

@@ -73,11 +73,11 @@ int OpenRaider::loadConfig(const char *config) {
73 73
     assert(config[0] != '\0');
74 74
 
75 75
     char *configFile = fullPath(config, 0);
76
-    printf("Loading config from \"%s\"...\n", configFile);
76
+    mConsole->print("Loading config from \"%s\"...", configFile);
77 77
 
78 78
     FILE *f = fopen(configFile, "r");
79 79
     if (f == NULL) {
80
-        printf("Could not open file!\n");
80
+        mConsole->print("Could not open file!");
81 81
         return -1;
82 82
     }
83 83
 
@@ -132,7 +132,7 @@ int OpenRaider::command(const char *command, std::vector<char *> *args) {
132 132
 
133 133
     if (strcmp(command, "set") == 0) {
134 134
         if (args->size() != 2) {
135
-            printf("Invalid use of set-command ");
135
+            mConsole->print("Invalid use of set-command ");
136 136
             printStringVector(args);
137 137
             printf("\n");
138 138
             return -2;
@@ -141,15 +141,17 @@ int OpenRaider::command(const char *command, std::vector<char *> *args) {
141 141
         }
142 142
     } else if (strcmp(command, "bind") == 0) {
143 143
         if (args->size() != 2) {
144
-            printf("Invalid use of bind-command ");
144
+            mConsole->print("Invalid use of bind-command ");
145 145
             printStringVector(args);
146 146
             printf("\n");
147 147
             return -3;
148 148
         } else {
149 149
             return bind(args->at(0), args->at(1));
150 150
         }
151
+    } else if (strcmp(command, "quit") == 0) {
152
+        exit(0);
151 153
     } else {
152
-        printf("Unknown command: %s ", command);
154
+        mConsole->print("Unknown command: %s ", command);
153 155
         printStringVector(args);
154 156
         printf("\n");
155 157
         return -1;
@@ -206,14 +208,14 @@ int OpenRaider::set(const char *var, const char *value) {
206 208
         // value has format like "\"1024x768\""
207 209
         unsigned int w = DEFAULT_WIDTH, h = DEFAULT_HEIGHT;
208 210
         if (sscanf(value, "\"%dx%d\"", &w, &h) != 2) {
209
-            printf("set-size-Error: Invalid value (%s)\n", value);
211
+            mConsole->print("set-size-Error: Invalid value (%s)", value);
210 212
             return -2;
211 213
         }
212 214
         mWindow->setSize(w, h);
213 215
     } else if (strcmp(var, "fullscreen") == 0) {
214 216
         bool fullscreen = false;
215 217
         if (readBool(value, &fullscreen) != 0) {
216
-            printf("set-fullscreen-Error: Invalid value (%s)\n", value);
218
+            mConsole->print("set-fullscreen-Error: Invalid value (%s)", value);
217 219
             return -3;
218 220
         }
219 221
         mWindow->setFullscreen(fullscreen);
@@ -222,28 +224,28 @@ int OpenRaider::set(const char *var, const char *value) {
222 224
     } else if (strcmp(var, "audio") == 0) {
223 225
         bool audio = false;
224 226
         if (readBool(value, &audio) != 0) {
225
-            printf("set-audio-Error: Invalid value (%s)\n", value);
227
+            mConsole->print("set-audio-Error: Invalid value (%s)", value);
226 228
             return -4;
227 229
         }
228 230
         mSound->setEnabled(audio);
229 231
     } else if (strcmp(var, "volume") == 0) {
230 232
         float vol = 1.0f;
231 233
         if (sscanf(value, "%f", &vol) != 1) {
232
-            printf("set-volume-Error: Invalid value (%s)\n", value);
234
+            mConsole->print("set-volume-Error: Invalid value (%s)", value);
233 235
             return -5;
234 236
         }
235 237
         mSound->setVolume(vol);
236 238
     } else if (strcmp(var, "mouse_x") == 0) {
237 239
         float sense = 1.0f;
238 240
         if (sscanf(value, "%f", &sense) != 1) {
239
-            printf("set-mouse_x-Error: Invalid value (%s)\n", value);
241
+            mConsole->print("set-mouse_x-Error: Invalid value (%s)", value);
240 242
             return -6;
241 243
         }
242 244
         //! \todo mouse support
243 245
     } else if (strcmp(var, "mouse_y") == 0) {
244 246
         float sense = 1.0f;
245 247
         if (sscanf(value, "%f", &sense) != 1) {
246
-            printf("set-mouse_y-Error: Invalid value (%s)\n", value);
248
+            mConsole->print("set-mouse_y-Error: Invalid value (%s)", value);
247 249
             return -7;
248 250
         }
249 251
         //! \todo mouse support
@@ -266,7 +268,7 @@ int OpenRaider::set(const char *var, const char *value) {
266 268
         }
267 269
         delete [] quotes;
268 270
     } else {
269
-        printf("set-Error: Unknown variable (%s = %s)\n", var, value);
271
+        mConsole->print("set-Error: Unknown variable (%s = %s)", var, value);
270 272
         return -1;
271 273
     }
272 274
 
@@ -299,7 +301,7 @@ int OpenRaider::bind(const char *action, const char *key) {
299 301
     } else if (strcmp(tmp, "holster") == 0) {
300 302
         return bind(holster, key);
301 303
     } else {
302
-        printf("bind-Error: Unknown action (%s --> %s)\n", key, action);
304
+        mConsole->print("bind-Error: Unknown action (%s --> %s)", key, action);
303 305
         return -1;
304 306
     }
305 307
 }
@@ -317,7 +319,7 @@ int OpenRaider::bind(ActionEvents action, const char *key) {
317 319
             || ((c >= 'a') && (c <= 'z'))) {
318 320
             keyBindings[action] = (KeyboardButton)c;
319 321
         } else {
320
-            printf("bind-\'\'-Error: Unknown key (%s)\n", key);
322
+            mConsole->print("bind-\'\'-Error: Unknown key (%s)", key);
321 323
             return -1;
322 324
         }
323 325
     } else if ((key[0] == '\"') && (key[length - 1] == '\"')) {
@@ -424,13 +426,13 @@ int OpenRaider::bind(ActionEvents action, const char *key) {
424 426
         } else if (strcmp(tmp, "tab") == 0) {
425 427
             keyBindings[action] = tab;
426 428
         } else {
427
-            printf("bind-\"\"-Error: Unknown key (%s)\n", key);
429
+            mConsole->print("bind-\"\"-Error: Unknown key (%s)", key);
428 430
             delete [] tmp;
429 431
             return -2;
430 432
         }
431 433
         delete [] tmp;
432 434
     } else {
433
-        printf("bind-Error: Unknown key (%s)\n", key);
435
+        mConsole->print("bind-Error: Unknown key (%s)", key);
434 436
         return -3;
435 437
     }
436 438
     return 0;
@@ -464,12 +466,12 @@ void OpenRaider::loadPakFolderRecursive(const char *dir) {
464 466
                      || stringEndsWith(lowerPath, ".tr4")
465 467
                      || stringEndsWith(lowerPath, ".trc")) {
466 468
                     //if (m_tombraider.checkMime(fullPathMap) == 0) {
467
-                        // printf("Validated pak: '%s'\n", fullPathMap);
469
+                        // mConsole->print("Validated pak: '%s'", fullPathMap);
468 470
 
469 471
                         // Just load relative filename
470 472
                         mMapList.push_back(bufferString("%s", (fullPathMap + strlen(mPakDir))));
471 473
                     //} else {
472
-                    //    printf("ERROR: pak file '%s' not found or invalid\n", fullPathMap);
474
+                    //    mConsole->print("ERROR: pak file '%s' not found or invalid", fullPathMap);
473 475
                     //}
474 476
                 }
475 477
 
@@ -479,7 +481,7 @@ void OpenRaider::loadPakFolderRecursive(const char *dir) {
479 481
         }
480 482
         closedir(pakDir);
481 483
     } else {
482
-        printf("Could not open PAK dir %s!\n", dir);
484
+        mConsole->print("Could not open PAK dir %s!", dir);
483 485
     }
484 486
 }
485 487
 

+ 2
- 2
src/main.cpp Datei anzeigen

@@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
63 63
 
64 64
     // Create globals
65 65
     atexit(cleanupHandler);
66
-    printf("Initializing " VERSION "\n");
66
+    printf("Initializing %s", VERSION);
67 67
     gOpenRaider = new OpenRaider();
68 68
 
69 69
     // Try to load a configuration
@@ -80,7 +80,7 @@ int main(int argc, char *argv[]) {
80 80
     gOpenRaider->initialize();
81 81
 
82 82
     // Enter Main loop
83
-    printf("Starting " VERSION "\n");
83
+    gOpenRaider->mConsole->print("Starting %s", VERSION);
84 84
     gOpenRaider->run();
85 85
 
86 86
     return 0;

+ 10
- 5
src/utils/strings.cpp Datei anzeigen

@@ -97,13 +97,16 @@ char *bufferString(const char *string, va_list args) {
97 97
     int sz = 60;
98 98
     int n;
99 99
     char *text;
100
+    va_list tmp;
100 101
 
101 102
     assert(string != NULL);
102 103
     assert(string[0] != '\0');
103 104
 
104 105
     text = new char[sz];
105 106
 
106
-    n = vsnprintf(text, sz, string, args);
107
+    va_copy(tmp, args);
108
+    n = vsnprintf(text, sz, string, tmp);
109
+    va_end(tmp);
107 110
 
108 111
     if (n < 0) {
109 112
         delete [] text;
@@ -111,8 +114,10 @@ char *bufferString(const char *string, va_list args) {
111 114
     } else if (n >= sz) {
112 115
         sz = n + 1; // buffer too small
113 116
         delete [] text;
114
-        text = new char[sz];
115
-        n = vsnprintf(text, sz, string, args);
117
+        text = new char[sz + 1];
118
+        va_copy(tmp, args);
119
+        n = vsnprintf(text, sz, string, tmp);
120
+        va_end(tmp);
116 121
     }
117 122
 
118 123
     return text;
@@ -188,9 +193,9 @@ char *fullPath(const char *path, char end) {
188 193
     // Make sure ends in "end" char
189 194
     if ((lenPath > 0) && (end != 0) && (dir[lenPath - 1] != end)) {
190 195
         dir[lenPath] = end;
191
-        dir[lenPath + 1] = 0;
196
+        dir[lenPath + 1] = '\0';
192 197
     } else {
193
-        dir[lenPath] = 0;
198
+        dir[lenPath] = '\0';
194 199
     }
195 200
 
196 201
     return dir;

Laden…
Abbrechen
Speichern