Imported Upstream version 1.3
Manuel A. Fernandez Montecelo
12 years ago
0 | /* CON_console.c | |
1 | * Written By: Garrett Banuk <mongoose@mongeese.org> | |
2 | * This is free, just be sure to give me credit when using it | |
3 | * in any of your programs. | |
4 | */ | |
5 | ||
6 | #include <stdlib.h> | |
7 | #include <stdio.h> | |
8 | #include <string.h> | |
9 | #include <stdarg.h> | |
10 | #include "SDL.h" | |
11 | #include "SDL_image.h" | |
12 | #include "CON_console.h" | |
13 | #include "DT_drawtext.h" | |
14 | #include "internal.h" | |
15 | ||
16 | ||
17 | /* This contains a pointer to the "topmost" console. The console that | |
18 | * is currently taking keyboard input. */ | |
19 | static ConsoleInformation *Topmost; | |
20 | ||
21 | /* Forward declaration, this functions are only used internally. */ | |
22 | static void DrawCommandLine(); | |
23 | void Cursor_Left(ConsoleInformation *console); | |
24 | void Cursor_Right(ConsoleInformation *console); | |
25 | void Cursor_Home(ConsoleInformation *console); | |
26 | void Cursor_End(ConsoleInformation *console); | |
27 | void Cursor_Del(ConsoleInformation *console); | |
28 | void Cursor_BSpace(ConsoleInformation *console); | |
29 | void Cursor_Add(ConsoleInformation *console, SDL_Event *event); | |
30 | ||
31 | void Clear_Command(ConsoleInformation *console); | |
32 | void Clear_History(ConsoleInformation *console); | |
33 | ||
34 | void Command_Up(ConsoleInformation *console); | |
35 | void Command_Down(ConsoleInformation *console); | |
36 | ||
37 | ||
38 | /* Takes keys from the keyboard and inputs them to the console */ | |
39 | void CON_Events(SDL_Event *event) { | |
40 | ||
41 | if(Topmost != NULL && event->type == SDL_KEYDOWN) { switch (event->key.keysym.sym) { | |
42 | case SDLK_PAGEUP: | |
43 | Topmost->ConsoleScrollBack += CON_LINE_SCROLL; | |
44 | if(Topmost->ConsoleScrollBack > Topmost->LineBuffer-1) | |
45 | Topmost->ConsoleScrollBack = Topmost->LineBuffer-1; | |
46 | ||
47 | CON_UpdateConsole(Topmost); | |
48 | break; | |
49 | case SDLK_PAGEDOWN: | |
50 | Topmost->ConsoleScrollBack -= CON_LINE_SCROLL; | |
51 | if(Topmost->ConsoleScrollBack < 0) | |
52 | Topmost->ConsoleScrollBack = 0; | |
53 | CON_UpdateConsole(Topmost); | |
54 | break; | |
55 | case SDLK_HOME: | |
56 | if(event->key.keysym.mod & KMOD_SHIFT) { | |
57 | Topmost->ConsoleScrollBack = Topmost->LineBuffer-1; | |
58 | CON_UpdateConsole(Topmost); | |
59 | } else { | |
60 | Cursor_Home(Topmost); | |
61 | } | |
62 | break; | |
63 | case SDLK_END: | |
64 | if(event->key.keysym.mod & KMOD_SHIFT) { | |
65 | Topmost->ConsoleScrollBack = 0; | |
66 | CON_UpdateConsole(Topmost); | |
67 | } else { | |
68 | Cursor_End(Topmost); | |
69 | } | |
70 | break; | |
71 | case SDLK_UP: | |
72 | Command_Up(Topmost); | |
73 | break; | |
74 | case SDLK_DOWN: | |
75 | Command_Down(Topmost); | |
76 | break; | |
77 | case SDLK_LEFT: | |
78 | Cursor_Left(Topmost); | |
79 | break; | |
80 | case SDLK_RIGHT: | |
81 | Cursor_Right(Topmost); | |
82 | break; | |
83 | case SDLK_BACKSPACE: | |
84 | Cursor_BSpace(Topmost); | |
85 | break; | |
86 | case SDLK_DELETE: | |
87 | Cursor_Del(Topmost); | |
88 | break; | |
89 | case SDLK_INSERT: | |
90 | if(Topmost->InsMode) | |
91 | Topmost->InsMode = 0; | |
92 | else | |
93 | Topmost->InsMode = 1; | |
94 | break; | |
95 | case SDLK_TAB: | |
96 | CON_TabCompletion(Topmost); | |
97 | break; | |
98 | case SDLK_RETURN: | |
99 | if(strlen(Topmost->Command) > 0) { | |
100 | CON_NewLineCommand(Topmost); | |
101 | ||
102 | // copy the input into the past commands strings | |
103 | strcpy(Topmost->CommandLines[0], Topmost->Command); | |
104 | ||
105 | // display the command including the prompt | |
106 | CON_Out(Topmost, "%s%s", Topmost->Prompt, Topmost->Command); | |
107 | ||
108 | CON_CommandExecute(Topmost); | |
109 | ||
110 | Clear_Command(Topmost); | |
111 | Topmost->CommandScrollBack = -1; | |
112 | } | |
113 | CON_UpdateConsole(Topmost); | |
114 | break; | |
115 | case SDLK_a: | |
116 | if(event->key.keysym.mod & KMOD_CTRL) { | |
117 | Cursor_Home(Topmost); | |
118 | break; | |
119 | } | |
120 | case SDLK_e: | |
121 | if(event->key.keysym.mod & KMOD_CTRL) { | |
122 | Cursor_End(Topmost); | |
123 | break; | |
124 | } | |
125 | case SDLK_c: | |
126 | if(event->key.keysym.mod & KMOD_CTRL) { | |
127 | Clear_Command(Topmost); | |
128 | break; | |
129 | } | |
130 | case SDLK_l: | |
131 | if(event->key.keysym.mod & KMOD_CTRL) { | |
132 | Clear_History(Topmost); | |
133 | CON_UpdateConsole(Topmost); | |
134 | break; | |
135 | } | |
136 | default: | |
137 | if(Topmost->InsMode) | |
138 | Cursor_Add(Topmost, event); | |
139 | else { | |
140 | Cursor_Add(Topmost, event); | |
141 | Cursor_Del(Topmost); | |
142 | } | |
143 | } | |
144 | } | |
145 | } | |
146 | ||
147 | /* CON_SetAlphaGL() -- sets the alpha channel of an SDL_Surface to the | |
148 | * specified value. Preconditions: the surface in question is RGBA. | |
149 | * 0 <= a <= 255, where 0 is transparent and 255 is opaque. */ | |
150 | void CON_SetAlphaGL(SDL_Surface *s, int alpha) | |
151 | { | |
152 | Uint8 val; | |
153 | int x, y, w, h; | |
154 | Uint32 pixel; | |
155 | Uint8 r, g, b, a; | |
156 | SDL_PixelFormat *format; | |
157 | static char errorPrinted = 0; | |
158 | ||
159 | ||
160 | /* debugging assertions -- these slow you down, but hey, crashing sucks */ | |
161 | if(!s) | |
162 | { | |
163 | PRINT_ERROR("NULL Surface passed to CON_SetAlphaGL\n"); | |
164 | return; | |
165 | } | |
166 | ||
167 | /* clamp alpha value to 0...255 */ | |
168 | if(alpha < SDL_ALPHA_TRANSPARENT) | |
169 | val = SDL_ALPHA_TRANSPARENT; | |
170 | else if(alpha > SDL_ALPHA_OPAQUE) | |
171 | val = SDL_ALPHA_OPAQUE; | |
172 | else | |
173 | val = alpha; | |
174 | ||
175 | /* loop over alpha channels of each pixel, setting them appropriately. */ | |
176 | w = s->w; | |
177 | h = s->h; | |
178 | format = s->format; | |
179 | switch (format->BytesPerPixel) | |
180 | { | |
181 | case 2: | |
182 | /* 16-bit surfaces don't seem to support alpha channels. */ | |
183 | if(!errorPrinted) | |
184 | { | |
185 | errorPrinted = 1; | |
186 | PRINT_ERROR("16-bit SDL surfaces do not support alpha-blending under OpenGL.\n"); | |
187 | } | |
188 | break; | |
189 | case 4: | |
190 | { | |
191 | /* we can do this very quickly in 32-bit mode. 24-bit is more | |
192 | * difficult. And since 24-bit mode is reall the same as 32-bit, | |
193 | * so it usually ends up taking this route too. Win! Unroll loop | |
194 | * and use pointer arithmetic for extra speed. */ | |
195 | int numpixels = h * (w << 2); | |
196 | Uint8 *pix = (Uint8 *) (s->pixels); | |
197 | Uint8 *last = pix + numpixels; | |
198 | Uint8 *pixel; | |
199 | if((numpixels & 0x7) == 0) | |
200 | for(pixel = pix + 3; pixel < last; pixel += 32) | |
201 | *pixel = *(pixel + 4) = *(pixel + 8) = *(pixel + 12) = | |
202 | *(pixel + 16) = *(pixel + 20) = *(pixel + 24) = *(pixel + 28) = val; | |
203 | else | |
204 | for(pixel = pix + 3; pixel < last; pixel += 4) | |
205 | *pixel = val; | |
206 | break; | |
207 | } | |
208 | default: | |
209 | /* we have no choice but to do this slowly. <sigh> */ | |
210 | for(y = 0; y < h; ++y) | |
211 | for(x = 0; x < w; ++x) | |
212 | { | |
213 | char print = 0; | |
214 | /* Lock the surface for direct access to the pixels */ | |
215 | if(SDL_MUSTLOCK(s) && SDL_LockSurface(s) < 0) | |
216 | { | |
217 | PRINT_ERROR("Can't lock surface: "); | |
218 | fprintf(stderr, "%s\n", SDL_GetError()); | |
219 | return; | |
220 | } | |
221 | pixel = DT_GetPixel(s, x, y); | |
222 | if(x == 0 && y == 0) | |
223 | print = 1; | |
224 | SDL_GetRGBA(pixel, format, &r, &g, &b, &a); | |
225 | pixel = SDL_MapRGBA(format, r, g, b, val); | |
226 | SDL_GetRGBA(pixel, format, &r, &g, &b, &a); | |
227 | DT_PutPixel(s, x, y, pixel); | |
228 | ||
229 | /* unlock surface again */ | |
230 | if(SDL_MUSTLOCK(s)) | |
231 | SDL_UnlockSurface(s); | |
232 | } | |
233 | break; | |
234 | } | |
235 | } | |
236 | ||
237 | ||
238 | /* Updates the console buffer */ | |
239 | void CON_UpdateConsole(ConsoleInformation *console) | |
240 | { | |
241 | int loop; | |
242 | int loop2; | |
243 | int Screenlines = console->ConsoleSurface->h / DT_FontHeight(console->FontNumber); | |
244 | SDL_Rect DestRect; | |
245 | BitFont *CurrentFont = DT_FontPointer(console->FontNumber); | |
246 | ||
247 | ||
248 | ||
249 | SDL_FillRect(console->ConsoleSurface, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, console->ConsoleAlpha)); | |
250 | ||
251 | if(console->OutputScreen->flags & SDL_OPENGLBLIT) | |
252 | SDL_SetAlpha(console->ConsoleSurface, 0, SDL_ALPHA_OPAQUE); | |
253 | ||
254 | /* draw the background image if there is one */ | |
255 | if(console->BackgroundImage) | |
256 | { | |
257 | DestRect.x = console->BackX; | |
258 | DestRect.y = console->BackY; | |
259 | DestRect.w = console->BackgroundImage->w; | |
260 | DestRect.h = console->BackgroundImage->h; | |
261 | SDL_BlitSurface(console->BackgroundImage, NULL, console->ConsoleSurface, &DestRect); | |
262 | } | |
263 | ||
264 | /* Draw the text from the back buffers, calculate in the scrollback from the user | |
265 | * this is a normal SDL software-mode blit, so we need to temporarily set the ColorKey | |
266 | * for the font, and then clear it when we're done. | |
267 | */ | |
268 | if((console->OutputScreen->flags & SDL_OPENGLBLIT) && (console->OutputScreen->format->BytesPerPixel > 2)) | |
269 | { | |
270 | Uint32 *pix = (Uint32 *) (CurrentFont->FontSurface->pixels); | |
271 | SDL_SetColorKey(CurrentFont->FontSurface, SDL_SRCCOLORKEY, *pix); | |
272 | } | |
273 | ||
274 | ||
275 | //now draw text from last but second line to top | |
276 | for(loop = 0; loop < Screenlines-1 && loop < console->LineBuffer - console->ConsoleScrollBack; loop++) { | |
277 | if(console->ConsoleScrollBack != 0 && loop == 0) | |
278 | for(loop2 = 0; loop2 < (console->VChars / 5) + 1; loop2++) | |
279 | DT_DrawText(CON_SCROLL_INDICATOR, console->ConsoleSurface, console->FontNumber, CON_CHAR_BORDER + (loop2*5*DT_FontWidth(console->FontNumber)), (Screenlines - loop - 2) * DT_FontHeight(console->FontNumber)); | |
280 | else | |
281 | DT_DrawText(console->ConsoleLines[console->ConsoleScrollBack + loop], console->ConsoleSurface, console->FontNumber, CON_CHAR_BORDER, (Screenlines - loop - 2) * DT_FontHeight(console->FontNumber)); | |
282 | } | |
283 | ||
284 | if(console->OutputScreen->flags & SDL_OPENGLBLIT) | |
285 | SDL_SetColorKey(CurrentFont->FontSurface, 0, 0); | |
286 | } | |
287 | ||
288 | /* Draws the console buffer to the screen */ | |
289 | void CON_DrawConsole(ConsoleInformation *console) | |
290 | { | |
291 | SDL_Rect DestRect; | |
292 | ||
293 | ||
294 | /* Update the command line since it has a blinking cursor */ | |
295 | if(Topmost) DrawCommandLine(); | |
296 | ||
297 | /* before drawing, make sure the alpha channel of the console surface is set | |
298 | * properly. (sigh) I wish we didn't have to do this every frame... */ | |
299 | if(console->OutputScreen->flags & SDL_OPENGLBLIT) | |
300 | CON_SetAlphaGL(console->ConsoleSurface, console->ConsoleAlpha); | |
301 | ||
302 | /* Setup the rect the console is being blitted into based on the output screen */ | |
303 | DestRect.x = console->DispX; | |
304 | DestRect.y = console->DispY; | |
305 | DestRect.w = console->ConsoleSurface->w; | |
306 | DestRect.h = console->ConsoleSurface->h; | |
307 | ||
308 | SDL_BlitSurface(console->ConsoleSurface, NULL, console->OutputScreen, &DestRect); | |
309 | ||
310 | if(console->OutputScreen->flags & SDL_OPENGLBLIT) | |
311 | SDL_UpdateRects(console->OutputScreen, 1, &DestRect); | |
312 | } | |
313 | ||
314 | ||
315 | /* Initializes the console */ | |
316 | ConsoleInformation *CON_Init(const char *FontName, SDL_Surface *DisplayScreen, int lines, SDL_Rect rect) | |
317 | { | |
318 | int loop; | |
319 | SDL_Surface *Temp; | |
320 | ConsoleInformation *newinfo; | |
321 | ||
322 | ||
323 | /* Create a new console struct and init it. */ | |
324 | if((newinfo = (ConsoleInformation *) malloc(sizeof(ConsoleInformation))) == NULL) | |
325 | { | |
326 | PRINT_ERROR("Could not allocate the space for a new console info struct.\n"); | |
327 | return NULL; | |
328 | } | |
329 | newinfo->ConsoleLines = NULL; | |
330 | newinfo->CommandLines = NULL; | |
331 | newinfo->TotalConsoleLines = 0; | |
332 | newinfo->ConsoleScrollBack = 0; | |
333 | newinfo->TotalCommands = 0; | |
334 | newinfo->BackgroundImage = NULL; | |
335 | newinfo->ConsoleAlpha = SDL_ALPHA_OPAQUE; | |
336 | newinfo->Offset = 0; | |
337 | newinfo->InsMode = 1; | |
338 | newinfo->CursorPos = 0; | |
339 | newinfo->CommandScrollBack = 0; | |
340 | newinfo->OutputScreen = DisplayScreen; | |
341 | newinfo->Prompt = CON_DEFAULT_PROMPT; | |
342 | ||
343 | /* Load the consoles font */ | |
344 | if(-1 == (newinfo->FontNumber = DT_LoadFont(FontName, TRANS_FONT))) | |
345 | { | |
346 | PRINT_ERROR("Could not load the font "); | |
347 | fprintf(stderr, "\"%s\" for the console!\n", FontName); | |
348 | return NULL; | |
349 | } | |
350 | ||
351 | /* make sure that the size of the console is valid */ | |
352 | if(rect.w > newinfo->OutputScreen->w || rect.w < DT_FontWidth(newinfo->FontNumber) * 32) | |
353 | rect.w = newinfo->OutputScreen->w; | |
354 | if(rect.h > newinfo->OutputScreen->h || rect.h < DT_FontHeight(newinfo->FontNumber)) | |
355 | rect.h = newinfo->OutputScreen->h; | |
356 | if(rect.x < 0 || rect.x > newinfo->OutputScreen->w - rect.w) | |
357 | newinfo->DispX = 0; | |
358 | else | |
359 | newinfo->DispX = rect.x; | |
360 | if(rect.y < 0 || rect.y > newinfo->OutputScreen->h - rect.h) | |
361 | newinfo->DispY = 0; | |
362 | else | |
363 | newinfo->DispY = rect.y; | |
364 | ||
365 | /* load the console surface */ | |
366 | Temp = SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, newinfo->OutputScreen->format->BitsPerPixel, 0, 0, 0, 0); | |
367 | if(Temp == NULL) | |
368 | { | |
369 | PRINT_ERROR("Couldn't create the ConsoleSurface\n"); | |
370 | return NULL; | |
371 | } | |
372 | newinfo->ConsoleSurface = SDL_DisplayFormat(Temp); | |
373 | SDL_FreeSurface(Temp); | |
374 | SDL_FillRect(newinfo->ConsoleSurface, NULL, SDL_MapRGBA(newinfo->ConsoleSurface->format, 0, 0, 0, newinfo->ConsoleAlpha)); | |
375 | ||
376 | /* Load the dirty rectangle for user input */ | |
377 | Temp = SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, DT_FontHeight(newinfo->FontNumber), newinfo->OutputScreen->format->BitsPerPixel, 0, 0, 0, SDL_ALPHA_OPAQUE); | |
378 | if(Temp == NULL) | |
379 | { | |
380 | PRINT_ERROR("Couldn't create the InputBackground\n"); | |
381 | return NULL; | |
382 | } | |
383 | newinfo->InputBackground = SDL_DisplayFormat(Temp); | |
384 | SDL_FreeSurface(Temp); | |
385 | SDL_FillRect(newinfo->InputBackground, NULL, SDL_MapRGBA(newinfo->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE)); | |
386 | ||
387 | /* calculate the number of visible characters in the command line */ | |
388 | newinfo->VChars = (rect.w - CON_CHAR_BORDER) / DT_FontWidth(newinfo->FontNumber); | |
389 | if(newinfo->VChars > CON_CHARS_PER_LINE) newinfo->VChars = CON_CHARS_PER_LINE; | |
390 | ||
391 | /* We would like to have a minumum # of lines to guarentee we don't create a memory error */ | |
392 | if(rect.h / DT_FontHeight(newinfo->FontNumber) > lines) | |
393 | newinfo->LineBuffer = rect.h / DT_FontHeight(newinfo->FontNumber); | |
394 | else | |
395 | newinfo->LineBuffer = lines; | |
396 | ||
397 | ||
398 | newinfo->ConsoleLines = (char **)malloc(sizeof(char *) * newinfo->LineBuffer); | |
399 | newinfo->CommandLines = (char **)malloc(sizeof(char *) * newinfo->LineBuffer); | |
400 | for(loop = 0; loop <= newinfo->LineBuffer - 1; loop++) | |
401 | { | |
402 | newinfo->ConsoleLines[loop] = (char *)calloc(CON_CHARS_PER_LINE, sizeof(char)); | |
403 | newinfo->CommandLines[loop] = (char *)calloc(CON_CHARS_PER_LINE, sizeof(char)); | |
404 | } | |
405 | memset(newinfo->Command, 0, CON_CHARS_PER_LINE); | |
406 | memset(newinfo->LCommand, 0, CON_CHARS_PER_LINE); | |
407 | memset(newinfo->RCommand, 0, CON_CHARS_PER_LINE); | |
408 | memset(newinfo->VCommand, 0, CON_CHARS_PER_LINE); | |
409 | ||
410 | ||
411 | CON_Out(newinfo, "Console initialised."); | |
412 | CON_NewLineConsole(newinfo); | |
413 | CON_ListCommands(newinfo); | |
414 | ||
415 | return newinfo; | |
416 | } | |
417 | ||
418 | /* Frees all the memory loaded by the console */ | |
419 | void CON_Destroy(ConsoleInformation *console) | |
420 | { | |
421 | DT_DestroyDrawText(); | |
422 | CON_Free(console); | |
423 | } | |
424 | ||
425 | /* Frees all the memory loaded by the console */ | |
426 | void CON_Free(ConsoleInformation *console) | |
427 | { | |
428 | int i; | |
429 | ||
430 | ||
431 | CON_DestroyCommands(); | |
432 | for(i = 0; i <= console->LineBuffer - 1; i++) | |
433 | { | |
434 | free(console->ConsoleLines[i]); | |
435 | free(console->CommandLines[i]); | |
436 | } | |
437 | free(console->ConsoleLines); | |
438 | free(console->CommandLines); | |
439 | ||
440 | console->ConsoleLines = NULL; | |
441 | console->CommandLines = NULL; | |
442 | } | |
443 | ||
444 | ||
445 | /* Increments the console lines */ | |
446 | void CON_NewLineConsole(ConsoleInformation *console) | |
447 | { | |
448 | int loop; | |
449 | char *temp = console->ConsoleLines[console->LineBuffer - 1]; | |
450 | ||
451 | ||
452 | for(loop = console->LineBuffer - 1; loop > 0; loop--) | |
453 | console->ConsoleLines[loop] = console->ConsoleLines[loop - 1]; | |
454 | ||
455 | console->ConsoleLines[0] = temp; | |
456 | ||
457 | memset(console->ConsoleLines[0], 0, CON_CHARS_PER_LINE); | |
458 | if(console->TotalConsoleLines < console->LineBuffer - 1) | |
459 | console->TotalConsoleLines++; | |
460 | ||
461 | //Now adjust the ConsoleScrollBack | |
462 | //dont scroll if not at bottom | |
463 | if(console->ConsoleScrollBack != 0) | |
464 | console->ConsoleScrollBack++; | |
465 | //boundaries | |
466 | if(console->ConsoleScrollBack > console->LineBuffer-1) | |
467 | console->ConsoleScrollBack = console->LineBuffer-1; | |
468 | ||
469 | } | |
470 | ||
471 | ||
472 | /* Increments the command lines */ | |
473 | void CON_NewLineCommand(ConsoleInformation *console) | |
474 | { | |
475 | int loop; | |
476 | char *temp = console->CommandLines[console->LineBuffer - 1]; | |
477 | ||
478 | ||
479 | for(loop = console->LineBuffer - 1; loop > 0; loop--) | |
480 | console->CommandLines[loop] = console->CommandLines[loop - 1]; | |
481 | ||
482 | console->CommandLines[0] = temp; | |
483 | ||
484 | memset(console->CommandLines[0], 0, CON_CHARS_PER_LINE); | |
485 | if(console->TotalCommands < console->LineBuffer - 1) | |
486 | console->TotalCommands++; | |
487 | } | |
488 | ||
489 | /* Draws the command line the user is typing in to the screen */ | |
490 | /* completely rewritten by C.Wacha */ | |
491 | static void DrawCommandLine() | |
492 | { | |
493 | SDL_Rect rect; | |
494 | int x; | |
495 | int commandbuffer = Topmost->VChars - strlen(Topmost->Prompt)-1; // -1 to make cursor visible | |
496 | ||
497 | BitFont *CurrentFont = DT_FontPointer(Topmost->FontNumber); | |
498 | static Uint32 LastBlinkTime = 0; /* Last time the consoles cursor blinked */ | |
499 | static int LastCursorPos = 0; // Last Cursor Position | |
500 | static int Blink = 0; /* Is the cursor currently blinking */ | |
501 | ||
502 | //Concatenate the left and right side to command | |
503 | strcpy(Topmost->Command, Topmost->LCommand); | |
504 | strncat(Topmost->Command, Topmost->RCommand, strlen(Topmost->RCommand)); | |
505 | ||
506 | //calculate display offset from current cursor position | |
507 | if(Topmost->Offset < Topmost->CursorPos - commandbuffer) | |
508 | Topmost->Offset = Topmost->CursorPos - commandbuffer; | |
509 | if(Topmost->Offset > Topmost->CursorPos) | |
510 | Topmost->Offset = Topmost->CursorPos; | |
511 | ||
512 | //first add prompt to visible part | |
513 | strcpy(Topmost->VCommand, Topmost->Prompt); | |
514 | ||
515 | //then add the visible part of the command | |
516 | strncat(Topmost->VCommand, &Topmost->Command[Topmost->Offset], strlen(&Topmost->Command[Topmost->Offset])); | |
517 | ||
518 | //now display the result | |
519 | ||
520 | //once again we're drawing text, so in OpenGL context we need to temporarily set up | |
521 | //software-mode transparency. | |
522 | if(Topmost->OutputScreen->flags & SDL_OPENGLBLIT) { | |
523 | Uint32 *pix = (Uint32 *) (CurrentFont->FontSurface->pixels); | |
524 | SDL_SetColorKey(CurrentFont->FontSurface, SDL_SRCCOLORKEY, *pix); | |
525 | } | |
526 | ||
527 | //first of all restore InputBackground | |
528 | rect.x = 0; | |
529 | rect.y = Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber); | |
530 | rect.w = Topmost->InputBackground->w; | |
531 | rect.h = Topmost->InputBackground->h; | |
532 | SDL_BlitSurface(Topmost->InputBackground, NULL, Topmost->ConsoleSurface, &rect); | |
533 | ||
534 | //now add the text | |
535 | DT_DrawText(Topmost->VCommand, Topmost->ConsoleSurface, Topmost->FontNumber, CON_CHAR_BORDER, Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber)); | |
536 | ||
537 | //at last add the cursor | |
538 | //check if the blink period is over | |
539 | if(SDL_GetTicks() > LastBlinkTime) { | |
540 | LastBlinkTime = SDL_GetTicks() + CON_BLINK_RATE; | |
541 | if(Blink) | |
542 | Blink = 0; | |
543 | else | |
544 | Blink = 1; | |
545 | } | |
546 | ||
547 | //check if cursor has moved - if yes display cursor anyway | |
548 | if(Topmost->CursorPos != LastCursorPos) { | |
549 | LastCursorPos = Topmost->CursorPos; | |
550 | LastBlinkTime = SDL_GetTicks() + CON_BLINK_RATE; | |
551 | Blink = 1; | |
552 | } | |
553 | ||
554 | if(Blink) { | |
555 | x = CON_CHAR_BORDER + DT_FontWidth(Topmost->FontNumber) * (Topmost->CursorPos - Topmost->Offset + strlen(Topmost->Prompt)); | |
556 | if(Topmost->InsMode) | |
557 | DT_DrawText(CON_INS_CURSOR, Topmost->ConsoleSurface, Topmost->FontNumber, x, Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber)); | |
558 | else | |
559 | DT_DrawText(CON_OVR_CURSOR, Topmost->ConsoleSurface, Topmost->FontNumber, x, Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber)); | |
560 | } | |
561 | ||
562 | ||
563 | if(Topmost->OutputScreen->flags & SDL_OPENGLBLIT) { | |
564 | SDL_SetColorKey(CurrentFont->FontSurface, 0, 0); | |
565 | } | |
566 | } | |
567 | ||
568 | /* Outputs text to the console (in game and stdout), up to CON_CHARS_PER_LINE chars can be entered */ | |
569 | void CON_Out(ConsoleInformation *console, const char *str, ...) { | |
570 | va_list marker; | |
571 | //keep some space free for stuff like CON_Out(console, "blablabla %s", console->Command); | |
572 | char temp[CON_CHARS_PER_LINE + 128]; | |
573 | char* ptemp = temp; | |
574 | ||
575 | va_start(marker, str); | |
576 | vsnprintf(temp, CON_CHARS_PER_LINE + 127, str, marker); | |
577 | va_end(marker); | |
578 | ||
579 | if(console->ConsoleLines) { | |
580 | while(strlen(ptemp) > console->VChars) { | |
581 | CON_NewLineConsole(console); | |
582 | strncpy(console->ConsoleLines[0], ptemp, console->VChars); | |
583 | console->ConsoleLines[0][console->VChars] = '\0'; | |
584 | ptemp = &ptemp[console->VChars]; | |
585 | } | |
586 | CON_NewLineConsole(console); | |
587 | strncpy(console->ConsoleLines[0], ptemp, console->VChars); | |
588 | console->ConsoleLines[0][console->VChars] = '\0'; | |
589 | CON_UpdateConsole(console); | |
590 | } | |
591 | ||
592 | /* And print to stdout */ | |
593 | printf("%s\n", temp); | |
594 | } | |
595 | ||
596 | ||
597 | /* Sets the alpha level of the console, 0 turns off alpha blending */ | |
598 | void CON_Alpha(ConsoleInformation *console, unsigned char alpha) | |
599 | { | |
600 | /* store alpha as state! */ | |
601 | console->ConsoleAlpha = alpha; | |
602 | ||
603 | if((console->OutputScreen->flags & SDL_OPENGLBLIT) == 0) { | |
604 | if(alpha == 0) | |
605 | SDL_SetAlpha(console->ConsoleSurface, 0, alpha); | |
606 | else | |
607 | SDL_SetAlpha(console->ConsoleSurface, SDL_SRCALPHA, alpha); | |
608 | } | |
609 | ||
610 | CON_UpdateConsole(console); | |
611 | } | |
612 | ||
613 | ||
614 | /* Adds background image to the console, x and y based on consoles x and y */ | |
615 | int CON_Background(ConsoleInformation *console, const char *image, int x, int y) | |
616 | { | |
617 | SDL_Surface *temp; | |
618 | SDL_Rect backgroundsrc, backgrounddest; | |
619 | ||
620 | ||
621 | /* Free the background from the console */ | |
622 | if(image == NULL) { | |
623 | if(console->BackgroundImage ==NULL) | |
624 | SDL_FreeSurface(console->BackgroundImage); | |
625 | console->BackgroundImage = NULL; | |
626 | SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE)); | |
627 | return 0; | |
628 | } | |
629 | ||
630 | /* Load a new background */ | |
631 | temp = IMG_Load(image); | |
632 | if(!temp) { | |
633 | CON_Out(console, "Cannot load background %s.", image); | |
634 | return 1; | |
635 | } | |
636 | ||
637 | console->BackgroundImage = SDL_DisplayFormat(temp); | |
638 | SDL_FreeSurface(temp); | |
639 | console->BackX = x; | |
640 | console->BackY = y; | |
641 | ||
642 | backgroundsrc.x = 0; | |
643 | backgroundsrc.y = console->ConsoleSurface->h - DT_FontHeight(console->FontNumber) - console->BackY; | |
644 | backgroundsrc.w = console->BackgroundImage->w; | |
645 | backgroundsrc.h = console->InputBackground->h; | |
646 | ||
647 | backgrounddest.x = console->BackX; | |
648 | backgrounddest.y = 0; | |
649 | backgrounddest.w = console->BackgroundImage->w; | |
650 | backgrounddest.h = DT_FontHeight(console->FontNumber); | |
651 | ||
652 | SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE)); | |
653 | SDL_BlitSurface(console->BackgroundImage, &backgroundsrc, console->InputBackground, &backgrounddest); | |
654 | ||
655 | return 0; | |
656 | } | |
657 | ||
658 | /* takes a new x and y of the top left of the console window */ | |
659 | void CON_Position(ConsoleInformation *console, int x, int y) | |
660 | { | |
661 | if(x < 0 || x > console->OutputScreen->w - console->ConsoleSurface->w) | |
662 | console->DispX = 0; | |
663 | else | |
664 | console->DispX = x; | |
665 | ||
666 | if(y < 0 || y > console->OutputScreen->h - console->ConsoleSurface->h) | |
667 | console->DispY = 0; | |
668 | else | |
669 | console->DispY = y; | |
670 | } | |
671 | ||
672 | /* resizes the console, has to reset alot of stuff | |
673 | * returns 1 on error */ | |
674 | int CON_Resize(ConsoleInformation *console, SDL_Rect rect) | |
675 | { | |
676 | SDL_Surface *Temp; | |
677 | SDL_Rect backgroundsrc, backgrounddest; | |
678 | ||
679 | ||
680 | /* make sure that the size of the console is valid */ | |
681 | if(rect.w > console->OutputScreen->w || rect.w < DT_FontWidth(console->FontNumber) * 32) | |
682 | rect.w = console->OutputScreen->w; | |
683 | if(rect.h > console->OutputScreen->h || rect.h < DT_FontHeight(console->FontNumber)) | |
684 | rect.h = console->OutputScreen->h; | |
685 | if(rect.x < 0 || rect.x > console->OutputScreen->w - rect.w) | |
686 | console->DispX = 0; | |
687 | else | |
688 | console->DispX = rect.x; | |
689 | if(rect.y < 0 || rect.y > console->OutputScreen->h - rect.h) | |
690 | console->DispY = 0; | |
691 | else | |
692 | console->DispY = rect.y; | |
693 | ||
694 | /* load the console surface */ | |
695 | SDL_FreeSurface(console->ConsoleSurface); | |
696 | Temp = SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, rect.h, console->OutputScreen->format->BitsPerPixel, 0, 0, 0, 0); | |
697 | if(Temp == NULL) | |
698 | { | |
699 | PRINT_ERROR("Couldn't create the console->ConsoleSurface\n"); | |
700 | return 1; | |
701 | } | |
702 | console->ConsoleSurface = SDL_DisplayFormat(Temp); | |
703 | SDL_FreeSurface(Temp); | |
704 | ||
705 | /* Load the dirty rectangle for user input */ | |
706 | SDL_FreeSurface(console->InputBackground); | |
707 | Temp = SDL_CreateRGBSurface(SDL_SWSURFACE, rect.w, DT_FontHeight(console->FontNumber), console->OutputScreen->format->BitsPerPixel, 0, 0, 0, 0); | |
708 | if(Temp == NULL) | |
709 | { | |
710 | PRINT_ERROR("Couldn't create the input background\n"); | |
711 | return 1; | |
712 | } | |
713 | console->InputBackground = SDL_DisplayFormat(Temp); | |
714 | SDL_FreeSurface(Temp); | |
715 | ||
716 | /* Now reset some stuff dependent on the previous size */ | |
717 | console->ConsoleScrollBack = 0; | |
718 | ||
719 | /* Reload the background image (for the input text area) in the console */ | |
720 | if(console->BackgroundImage) | |
721 | { | |
722 | backgroundsrc.x = 0; | |
723 | backgroundsrc.y = console->ConsoleSurface->h - DT_FontHeight(console->FontNumber) - console->BackY; | |
724 | backgroundsrc.w = console->BackgroundImage->w; | |
725 | backgroundsrc.h = console->InputBackground->h; | |
726 | ||
727 | backgrounddest.x = console->BackX; | |
728 | backgrounddest.y = 0; | |
729 | backgrounddest.w = console->BackgroundImage->w; | |
730 | backgrounddest.h = DT_FontHeight(console->FontNumber); | |
731 | ||
732 | SDL_FillRect(console->InputBackground, NULL, SDL_MapRGBA(console->ConsoleSurface->format, 0, 0, 0, SDL_ALPHA_OPAQUE)); | |
733 | SDL_BlitSurface(console->BackgroundImage, &backgroundsrc, console->InputBackground, &backgrounddest); | |
734 | } | |
735 | ||
736 | return 0; | |
737 | } | |
738 | ||
739 | /* Sets the topmost console for input */ | |
740 | void CON_Topmost(ConsoleInformation *console) { | |
741 | SDL_Rect rect; | |
742 | ||
743 | // Make sure the blinking cursor is gone | |
744 | if(Topmost) { | |
745 | rect.x = 0; | |
746 | rect.y = Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber); | |
747 | rect.w = Topmost->InputBackground->w; | |
748 | rect.h = Topmost->InputBackground->h; | |
749 | SDL_BlitSurface(Topmost->InputBackground, NULL, Topmost->ConsoleSurface, &rect); | |
750 | DT_DrawText(Topmost->ConsoleLines[0], Topmost->ConsoleSurface, Topmost->FontNumber, CON_CHAR_BORDER, Topmost->ConsoleSurface->h - DT_FontHeight(Topmost->FontNumber)); | |
751 | } | |
752 | Topmost = console; | |
753 | } | |
754 | ||
755 | void CON_SetPrompt(ConsoleInformation *console, char* newprompt) { | |
756 | //check length so we can still see at least 1 char :-) | |
757 | if(strlen(newprompt) < console->VChars) | |
758 | console->Prompt = strdup(newprompt); | |
759 | else | |
760 | CON_Out(console, "prompt too long. (max. %i chars)", console->VChars - 1); | |
761 | } | |
762 | ||
763 | ||
764 | void Cursor_Left(ConsoleInformation *console){ | |
765 | char temp[CON_CHARS_PER_LINE]; | |
766 | ||
767 | if(Topmost->CursorPos > 0) { | |
768 | Topmost->CursorPos--; | |
769 | strcpy(temp, Topmost->RCommand); | |
770 | strcpy(Topmost->RCommand, &Topmost->LCommand[strlen(Topmost->LCommand)-1]); | |
771 | strcat(Topmost->RCommand, temp); | |
772 | Topmost->LCommand[strlen(Topmost->LCommand)-1] = '\0'; | |
773 | //CON_Out(Topmost, "L:%s, R:%s", Topmost->LCommand, Topmost->RCommand); | |
774 | } | |
775 | } | |
776 | ||
777 | void Cursor_Right(ConsoleInformation *console){ | |
778 | char temp[CON_CHARS_PER_LINE]; | |
779 | ||
780 | if(Topmost->CursorPos < strlen(Topmost->Command)) { | |
781 | Topmost->CursorPos++; | |
782 | strncat(Topmost->LCommand, Topmost->RCommand, 1); | |
783 | strcpy(temp, Topmost->RCommand); | |
784 | strcpy(Topmost->RCommand, &temp[1]); | |
785 | //CON_Out(Topmost, "L:%s, R:%s", Topmost->LCommand, Topmost->RCommand); | |
786 | } | |
787 | } | |
788 | ||
789 | void Cursor_Home(ConsoleInformation *console){ | |
790 | char temp[CON_CHARS_PER_LINE]; | |
791 | ||
792 | Topmost->CursorPos = 0; | |
793 | strcpy(temp, Topmost->RCommand); | |
794 | strcpy(Topmost->RCommand, Topmost->LCommand); | |
795 | strncat(Topmost->RCommand, temp, strlen(temp)); | |
796 | memset(Topmost->LCommand, 0, CON_CHARS_PER_LINE); | |
797 | } | |
798 | ||
799 | void Cursor_End(ConsoleInformation *console){ | |
800 | Topmost->CursorPos = strlen(Topmost->Command); | |
801 | strncat(Topmost->LCommand, Topmost->RCommand, strlen(Topmost->RCommand)); | |
802 | memset(Topmost->RCommand, 0, CON_CHARS_PER_LINE); | |
803 | } | |
804 | ||
805 | void Cursor_Del(ConsoleInformation *console) { | |
806 | char temp[CON_CHARS_PER_LINE]; | |
807 | ||
808 | if(strlen(Topmost->RCommand) > 0) { | |
809 | strcpy(temp, Topmost->RCommand); | |
810 | strcpy(Topmost->RCommand, &temp[1]); | |
811 | } | |
812 | } | |
813 | ||
814 | void Cursor_BSpace(ConsoleInformation *console) { | |
815 | if(Topmost->CursorPos > 0) { | |
816 | Topmost->CursorPos--; | |
817 | Topmost->Offset--; | |
818 | if(Topmost->Offset < 0) Topmost->Offset = 0; | |
819 | Topmost->LCommand[strlen(Topmost->LCommand)-1] = '\0'; | |
820 | } | |
821 | } | |
822 | ||
823 | void Cursor_Add(ConsoleInformation *console, SDL_Event *event) { | |
824 | if(strlen(Topmost->Command) < CON_CHARS_PER_LINE - 1 && event->key.keysym.unicode) { | |
825 | Topmost->CursorPos++; | |
826 | Topmost->LCommand[strlen(Topmost->LCommand)] = (char)event->key.keysym.unicode; | |
827 | Topmost->LCommand[strlen(Topmost->LCommand)] = '\0'; | |
828 | } | |
829 | } | |
830 | ||
831 | void Clear_Command(ConsoleInformation *console) { | |
832 | Topmost->CursorPos = 0; | |
833 | memset(Topmost->VCommand, 0, CON_CHARS_PER_LINE); | |
834 | memset(Topmost->Command, 0, CON_CHARS_PER_LINE); | |
835 | memset(Topmost->LCommand, 0, CON_CHARS_PER_LINE); | |
836 | memset(Topmost->RCommand, 0, CON_CHARS_PER_LINE); | |
837 | } | |
838 | ||
839 | void Clear_History(ConsoleInformation *console) { | |
840 | int loop; | |
841 | ||
842 | for(loop = 0; loop <= console->LineBuffer - 1; loop++) | |
843 | memset(console->ConsoleLines[loop], 0, CON_CHARS_PER_LINE); | |
844 | } | |
845 | ||
846 | void Command_Up(ConsoleInformation *console) { | |
847 | if(console->CommandScrollBack < console->TotalCommands - 1) { | |
848 | /* move back a line in the command strings and copy the command to the current input string */ | |
849 | console->CommandScrollBack++; | |
850 | memset(console->RCommand, 0, CON_CHARS_PER_LINE); | |
851 | console->Offset = 0; | |
852 | strcpy(console->LCommand, console->CommandLines[console->CommandScrollBack]); | |
853 | console->CursorPos = strlen(console->CommandLines[console->CommandScrollBack]); | |
854 | CON_UpdateConsole(console); | |
855 | } | |
856 | } | |
857 | ||
858 | void Command_Down(ConsoleInformation *console) { | |
859 | if(console->CommandScrollBack > -1) { | |
860 | /* move forward a line in the command strings and copy the command to the current input string */ | |
861 | console->CommandScrollBack--; | |
862 | memset(console->RCommand, 0, CON_CHARS_PER_LINE); | |
863 | memset(console->LCommand, 0, CON_CHARS_PER_LINE); | |
864 | console->Offset = 0; | |
865 | if(console->CommandScrollBack > -1) | |
866 | strcpy(console->LCommand, console->CommandLines[console->CommandScrollBack]); | |
867 | console->CursorPos = strlen(console->LCommand); | |
868 | CON_UpdateConsole(console); | |
869 | } | |
870 | } | |
871 |
0 | #ifndef CON_console_H | |
1 | #define CON_console_H | |
2 | ||
3 | ||
4 | #define CON_CHARS_PER_LINE 128 | |
5 | #define CON_BLINK_RATE 500 | |
6 | #define CON_CHAR_BORDER 4 | |
7 | #define CON_DEFAULT_PROMPT "]" | |
8 | #define CON_LINE_SCROLL 2 | |
9 | #define CON_SCROLL_INDICATOR "^" | |
10 | #define CON_INS_CURSOR "_" | |
11 | #define CON_OVR_CURSOR "|" | |
12 | ||
13 | ||
14 | #ifdef __cplusplus | |
15 | extern "C" | |
16 | { | |
17 | #endif | |
18 | ||
19 | /* This is a struct for each consoles data */ | |
20 | typedef struct console_information_td | |
21 | { | |
22 | char **ConsoleLines; // List of all the past lines | |
23 | char **CommandLines; // List of all the past commands | |
24 | int TotalConsoleLines; // Total number of lines in the console | |
25 | int ConsoleScrollBack; // How much the users scrolled back in the console | |
26 | int TotalCommands; // Number of commands in the Back Commands | |
27 | int FontNumber; // This is the number of the font for the console | |
28 | int LineBuffer; // The number of visible lines in the console (autocalculated) | |
29 | int VChars; // The number of visible characters in one console line (autocalculated) | |
30 | int BackX, BackY; // Background images x and y coords | |
31 | char* Prompt; // Prompt displayed in command line | |
32 | char Command[CON_CHARS_PER_LINE]; // current command in command line = lcommand + rcommand | |
33 | char RCommand[CON_CHARS_PER_LINE]; // left hand side of cursor | |
34 | char LCommand[CON_CHARS_PER_LINE]; // right hand side of cursor | |
35 | char VCommand[CON_CHARS_PER_LINE]; // current visible command line | |
36 | int CursorPos; // Current cursor position in CurrentCommand | |
37 | int Offset; // CommandOffset (first visible char of command) - if command is too long to fit into console | |
38 | int InsMode; // Insert or Overwrite characters? | |
39 | SDL_Surface *ConsoleSurface; // Surface of the console | |
40 | SDL_Surface *OutputScreen; // This is the screen to draw the console to | |
41 | SDL_Surface *BackgroundImage; // Background image for the console | |
42 | SDL_Surface *InputBackground; // Dirty rectangle to draw over behind the users background | |
43 | int DispX, DispY; // The top left x and y coords of the console on the display screen | |
44 | unsigned char ConsoleAlpha; // The consoles alpha level | |
45 | int CommandScrollBack; // How much the users scrolled back in the command lines | |
46 | } ConsoleInformation; | |
47 | ||
48 | ||
49 | ||
50 | void CON_Events(SDL_Event *event); | |
51 | void CON_DrawConsole(ConsoleInformation *console); | |
52 | ConsoleInformation *CON_Init(const char *FontName, SDL_Surface *DisplayScreen, int lines, SDL_Rect rect); | |
53 | void CON_Destroy(ConsoleInformation *console); | |
54 | void CON_Free(ConsoleInformation *console); | |
55 | void CON_Out(ConsoleInformation *console, const char *str, ...); | |
56 | void CON_Alpha(ConsoleInformation *console, unsigned char alpha); | |
57 | int CON_Background(ConsoleInformation *console, const char *image, int x, int y); | |
58 | void CON_Position(ConsoleInformation *console, int x, int y); | |
59 | int CON_Resize(ConsoleInformation *console, SDL_Rect rect); | |
60 | void CON_NewLineConsole(ConsoleInformation *console); | |
61 | void CON_NewLineCommand(ConsoleInformation *console); | |
62 | void CON_UpdateConsole(ConsoleInformation *console); | |
63 | void CON_Topmost(ConsoleInformation *console); | |
64 | void CON_SetPrompt(ConsoleInformation *console, char* newprompt); | |
65 | ||
66 | void Cursor_Left(ConsoleInformation *console); | |
67 | void Cursor_Right(ConsoleInformation *console); | |
68 | void Cursor_Home(ConsoleInformation *console); | |
69 | void Cursor_End(ConsoleInformation *console); | |
70 | void Cursor_Del(ConsoleInformation *console); | |
71 | void Cursor_BSpace(ConsoleInformation *console); | |
72 | void Cursor_Add(ConsoleInformation *console, SDL_Event *event); | |
73 | ||
74 | void Clear_Command(ConsoleInformation *console); | |
75 | void Clear_History(ConsoleInformation *console); | |
76 | ||
77 | ||
78 | //Console Commands | |
79 | ||
80 | typedef struct CommandInfo_td | |
81 | { | |
82 | void (*CommandCallback)(ConsoleInformation *console, char *Parameters); | |
83 | char *CommandWord; | |
84 | struct CommandInfo_td *NextCommand; | |
85 | } CommandInfo; | |
86 | ||
87 | ||
88 | void CON_SendFullCommand(int sendOn); | |
89 | void CON_CommandExecute(ConsoleInformation *console); | |
90 | void CON_AddCommand(void (*CommandCallback)(ConsoleInformation *console, char *Parameters), const char *CommandWord); | |
91 | void CON_TabCompletion(ConsoleInformation *console); | |
92 | void CON_ListCommands(ConsoleInformation *console); | |
93 | void CON_DestroyCommands(); | |
94 | ||
95 | ||
96 | #ifdef __cplusplus | |
97 | }; | |
98 | #endif | |
99 | ||
100 | #endif | |
101 | ||
102 |
0 | /* CON_consolecommands.c | |
1 | * Written By: Garrett Banuk <mongoose@mongeese.org> | |
2 | * This is free, just be sure to give me credit when using it | |
3 | * in any of your programs. | |
4 | */ | |
5 | ||
6 | ||
7 | #include <stdio.h> | |
8 | #include <string.h> | |
9 | #include <stdlib.h> | |
10 | #include "SDL.h" | |
11 | #include "CON_console.h" | |
12 | #include "internal.h" | |
13 | ||
14 | ||
15 | /* Linked list of all the commands. */ | |
16 | static CommandInfo *Commands = NULL; | |
17 | static int SendCommand = 0; | |
18 | ||
19 | ||
20 | /* executes the command passed in from the string */ | |
21 | void CON_CommandExecute(ConsoleInformation *console) | |
22 | { | |
23 | char Command[CON_CHARS_PER_LINE]; | |
24 | char *BackStrings = console->Command; | |
25 | CommandInfo *CurrentCommand = Commands; | |
26 | ||
27 | /* Get the command out of the string */ | |
28 | if(EOF == sscanf(BackStrings, "%s", Command)) | |
29 | return; | |
30 | ||
31 | CurrentCommand = Commands; | |
32 | while(CurrentCommand) { | |
33 | if(0 == strcmp(Command, CurrentCommand->CommandWord)) { | |
34 | if (SendCommand) | |
35 | CurrentCommand->CommandCallback(console, BackStrings); | |
36 | else | |
37 | CurrentCommand->CommandCallback(console, BackStrings+strlen(Command)+1); | |
38 | return; | |
39 | } | |
40 | CurrentCommand = CurrentCommand->NextCommand; | |
41 | } | |
42 | CON_Out(console, "Unknown Command \"%s\"", Command); | |
43 | } | |
44 | ||
45 | /* Use this to add commands. | |
46 | * Pass in a pointer to a funtion that will take a string which contains the | |
47 | * arguments passed to the command. Second parameter is the command to execute | |
48 | * on. | |
49 | */ | |
50 | void CON_AddCommand(void(*CommandCallback)(ConsoleInformation *console, char *Parameters), const char *CommandWord) | |
51 | { | |
52 | CommandInfo **CurrentCommand = &Commands; | |
53 | ||
54 | ||
55 | while(*CurrentCommand) | |
56 | CurrentCommand = &((*CurrentCommand)->NextCommand); | |
57 | ||
58 | /* Add a command to the list */ | |
59 | *CurrentCommand = (CommandInfo*)malloc(sizeof(CommandInfo)); | |
60 | (*CurrentCommand)->CommandCallback = CommandCallback; | |
61 | (*CurrentCommand)->CommandWord = (char*)malloc(strlen(CommandWord)+1); | |
62 | strcpy((*CurrentCommand)->CommandWord, CommandWord); | |
63 | (*CurrentCommand)->NextCommand = NULL; | |
64 | } | |
65 | ||
66 | /* tab completes commands | |
67 | * It takes a string to complete and a pointer to the strings length. The strings | |
68 | * length will be modified if the command is completed. */ | |
69 | void CON_TabCompletion(ConsoleInformation *console) | |
70 | { | |
71 | int Matches = 0; | |
72 | int *location = &console->CursorPos; | |
73 | char *CommandLine = console->LCommand; | |
74 | char temp[CON_CHARS_PER_LINE]; | |
75 | CommandInfo *CurrentCommand; | |
76 | ||
77 | // Don't try to complete if nothing is entered | |
78 | if(*location == 0) | |
79 | return; | |
80 | ||
81 | ||
82 | /* Find all the commands that match */ | |
83 | CurrentCommand = Commands; | |
84 | while(CurrentCommand) | |
85 | { | |
86 | if(0 == strncmp(CommandLine, CurrentCommand->CommandWord, strlen(CommandLine))) | |
87 | Matches++; | |
88 | CurrentCommand = CurrentCommand->NextCommand; | |
89 | } | |
90 | ||
91 | /* if we got one match, find it again and execute it */ | |
92 | if(Matches == 1) | |
93 | { | |
94 | CurrentCommand = Commands; | |
95 | while(CurrentCommand) | |
96 | { | |
97 | if(0 == strncmp(CommandLine, CurrentCommand->CommandWord, strlen(CommandLine))) | |
98 | { | |
99 | strcpy(CommandLine, CurrentCommand->CommandWord); | |
100 | CommandLine[strlen(CurrentCommand->CommandWord)] = ' '; | |
101 | *location = strlen(CurrentCommand->CommandWord)+1; | |
102 | CON_UpdateConsole(console); | |
103 | break; | |
104 | } | |
105 | CurrentCommand = CurrentCommand->NextCommand; | |
106 | } | |
107 | } | |
108 | else if(Matches > 1)/* multiple matches so print them out to the user */ | |
109 | { | |
110 | CON_NewLineConsole(console); | |
111 | CurrentCommand = Commands; | |
112 | while(CurrentCommand) | |
113 | { | |
114 | if(0 == strncmp(CommandLine, CurrentCommand->CommandWord, strlen(CommandLine))) { | |
115 | strcpy(temp, " "); | |
116 | strcpy(&temp[5], CurrentCommand->CommandWord); | |
117 | CON_Out(console, temp); | |
118 | } | |
119 | CurrentCommand = CurrentCommand->NextCommand; | |
120 | } | |
121 | } | |
122 | else if(Matches == 0) { | |
123 | // Thats not very interesting.. | |
124 | //CON_Out(console, "No match"); | |
125 | } | |
126 | } | |
127 | ||
128 | ||
129 | /* Lists all the commands to be used in the console */ | |
130 | void CON_ListCommands(ConsoleInformation *console) | |
131 | { | |
132 | CommandInfo *CurrentCommand = Commands; | |
133 | ||
134 | CON_Out(console, " "); | |
135 | while(CurrentCommand) | |
136 | { | |
137 | CON_Out(console, " %s", CurrentCommand->CommandWord); | |
138 | CurrentCommand = CurrentCommand->NextCommand; | |
139 | } | |
140 | ||
141 | } | |
142 | ||
143 | /* sends the command word used and the parameters back */ | |
144 | void CON_SendFullCommand(int sendOn) | |
145 | { | |
146 | SendCommand = sendOn; | |
147 | } | |
148 | ||
149 | /* This frees all the memory used by the commands */ | |
150 | void CON_DestroyCommands() | |
151 | { | |
152 | CommandInfo *CurrentCommand = Commands; | |
153 | CommandInfo *temp; | |
154 | ||
155 | while(CurrentCommand) | |
156 | { | |
157 | temp = CurrentCommand; | |
158 | CurrentCommand = CurrentCommand->NextCommand; | |
159 | ||
160 | free(temp->CommandWord); | |
161 | free(temp); | |
162 | } | |
163 | Commands = NULL; | |
164 | } | |
165 | ||
166 |
0 | /* DT_drawtext.c | |
1 | * Written By: Garrett Banuk <mongoose@mongeese.org> | |
2 | * This is free, just be sure to give me credit when using it | |
3 | * in any of your programs. | |
4 | */ | |
5 | ||
6 | #include <string.h> | |
7 | #include <stdio.h> | |
8 | #include <stdlib.h> | |
9 | #include "SDL.h" | |
10 | #include "SDL_image.h" | |
11 | #include "DT_drawtext.h" | |
12 | #include "internal.h" | |
13 | ||
14 | ||
15 | static BitFont *BitFonts = NULL; /* Linked list of fonts */ | |
16 | ||
17 | ||
18 | /* sets the transparency value for the font in question. assumes that | |
19 | * we're in an OpenGL context. */ | |
20 | void DT_SetFontAlphaGL(int FontNumber, int a) | |
21 | { | |
22 | unsigned char val; | |
23 | BitFont *CurrentFont; | |
24 | unsigned char r_targ, g_targ, b_targ; | |
25 | int i, imax; | |
26 | unsigned char *pix; | |
27 | ||
28 | /* get pointer to font */ | |
29 | CurrentFont = DT_FontPointer(FontNumber); | |
30 | if(CurrentFont == NULL) | |
31 | { | |
32 | PRINT_ERROR("Setting font alpha for non-existent font!\n"); | |
33 | return; | |
34 | } | |
35 | if(CurrentFont->FontSurface->format->BytesPerPixel == 2) | |
36 | { | |
37 | PRINT_ERROR("16-bit SDL surfaces do not support alpha-blending under OpenGL\n"); | |
38 | return; | |
39 | } | |
40 | if(a < SDL_ALPHA_TRANSPARENT) | |
41 | val = SDL_ALPHA_TRANSPARENT; | |
42 | else if(a > SDL_ALPHA_OPAQUE) | |
43 | val = SDL_ALPHA_OPAQUE; | |
44 | else | |
45 | val = a; | |
46 | ||
47 | /* iterate over all pixels in the font surface. For each | |
48 | * pixel that is (255,0,255), set its alpha channel | |
49 | * appropriately. */ | |
50 | imax = CurrentFont->FontSurface->h * (CurrentFont->FontSurface->w << 2); | |
51 | pix = (unsigned char *)(CurrentFont->FontSurface->pixels); | |
52 | r_targ = 255; /*pix[0]; */ | |
53 | g_targ = 0; /*pix[1]; */ | |
54 | b_targ = 255; /*pix[2]; */ | |
55 | for(i = 3; i < imax; i += 4) | |
56 | if(pix[i - 3] == r_targ && pix[i - 2] == g_targ && pix[i - 1] == b_targ) | |
57 | pix[i] = val; | |
58 | /* also make sure that alpha blending is disabled for the font | |
59 | surface. */ | |
60 | SDL_SetAlpha(CurrentFont->FontSurface, 0, SDL_ALPHA_OPAQUE); | |
61 | } | |
62 | ||
63 | /* Loads the font into a new struct | |
64 | * returns -1 as an error else it returns the number | |
65 | * of the font for the user to use | |
66 | */ | |
67 | int DT_LoadFont(const char *BitmapName, int flags) | |
68 | { | |
69 | int FontNumber = 0; | |
70 | BitFont **CurrentFont = &BitFonts; | |
71 | SDL_Surface *Temp; | |
72 | ||
73 | ||
74 | while(*CurrentFont) | |
75 | { | |
76 | CurrentFont = &((*CurrentFont)->NextFont); | |
77 | FontNumber++; | |
78 | } | |
79 | ||
80 | /* load the font bitmap */ | |
81 | if(NULL == (Temp = IMG_Load(BitmapName))) | |
82 | { | |
83 | PRINT_ERROR("Cannot load file "); | |
84 | printf("%s\n", BitmapName); | |
85 | return -1; | |
86 | } | |
87 | ||
88 | /* Add a font to the list */ | |
89 | *CurrentFont = (BitFont *) malloc(sizeof(BitFont)); | |
90 | ||
91 | (*CurrentFont)->FontSurface = SDL_DisplayFormat(Temp); | |
92 | SDL_FreeSurface(Temp); | |
93 | ||
94 | (*CurrentFont)->CharWidth = (*CurrentFont)->FontSurface->w / 256; | |
95 | (*CurrentFont)->CharHeight = (*CurrentFont)->FontSurface->h; | |
96 | (*CurrentFont)->FontNumber = FontNumber; | |
97 | (*CurrentFont)->NextFont = NULL; | |
98 | ||
99 | ||
100 | /* Set font as transparent if the flag is set. The assumption we'll go on | |
101 | * is that the first pixel of the font image will be the color we should treat | |
102 | * as transparent. | |
103 | */ | |
104 | if(flags & TRANS_FONT) | |
105 | { | |
106 | if(SDL_GetVideoSurface()->flags & SDL_OPENGLBLIT) | |
107 | DT_SetFontAlphaGL(FontNumber, SDL_ALPHA_TRANSPARENT); | |
108 | else | |
109 | SDL_SetColorKey((*CurrentFont)->FontSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB((*CurrentFont)->FontSurface->format, 255, 0, 255)); | |
110 | } | |
111 | else if(SDL_GetVideoSurface()->flags & SDL_OPENGLBLIT) | |
112 | DT_SetFontAlphaGL(FontNumber, SDL_ALPHA_OPAQUE); | |
113 | ||
114 | return FontNumber; | |
115 | } | |
116 | ||
117 | /* Takes the font type, coords, and text to draw to the surface*/ | |
118 | void DT_DrawText(const char *string, SDL_Surface *surface, int FontType, int x, int y) | |
119 | { | |
120 | int loop; | |
121 | int characters; | |
122 | int current; | |
123 | SDL_Rect SourceRect, DestRect; | |
124 | BitFont *CurrentFont; | |
125 | ||
126 | CurrentFont = DT_FontPointer(FontType); | |
127 | ||
128 | /* see how many characters can fit on the screen */ | |
129 | if(x > surface->w || y > surface->h) | |
130 | return; | |
131 | ||
132 | if(strlen(string) < (surface->w - x) / CurrentFont->CharWidth) | |
133 | characters = strlen(string); | |
134 | else | |
135 | characters = (surface->w - x) / CurrentFont->CharWidth; | |
136 | ||
137 | DestRect.x = x; | |
138 | DestRect.y = y; | |
139 | DestRect.w = CurrentFont->CharWidth; | |
140 | DestRect.h = CurrentFont->CharHeight; | |
141 | ||
142 | SourceRect.y = 0; | |
143 | SourceRect.w = CurrentFont->CharWidth; | |
144 | SourceRect.h = CurrentFont->CharHeight; | |
145 | ||
146 | /* Now draw it */ | |
147 | for(loop = 0; loop < characters; loop++) | |
148 | { | |
149 | current = string[loop]; | |
150 | if (current<0 || current > 255) | |
151 | current = 0; | |
152 | //SourceRect.x = string[loop] * CurrentFont->CharWidth; | |
153 | SourceRect.x = current * CurrentFont->CharWidth; | |
154 | SDL_BlitSurface(CurrentFont->FontSurface, &SourceRect, surface, &DestRect); | |
155 | DestRect.x += CurrentFont->CharWidth; | |
156 | } | |
157 | /* if we're in OpenGL-mode, we need to manually update after blitting. */ | |
158 | if(surface->flags & SDL_OPENGLBLIT) | |
159 | { | |
160 | DestRect.x = x; | |
161 | DestRect.w = characters * CurrentFont->CharWidth; | |
162 | SDL_UpdateRects(surface, 1, &DestRect); | |
163 | } | |
164 | } | |
165 | ||
166 | ||
167 | /* Returns the height of the font numbers character | |
168 | * returns 0 if the fontnumber was invalid */ | |
169 | int DT_FontHeight(int FontNumber) | |
170 | { | |
171 | BitFont *CurrentFont; | |
172 | ||
173 | CurrentFont = DT_FontPointer(FontNumber); | |
174 | if(CurrentFont) | |
175 | return CurrentFont->CharHeight; | |
176 | else | |
177 | return 0; | |
178 | } | |
179 | ||
180 | /* Returns the width of the font numbers charcter */ | |
181 | int DT_FontWidth(int FontNumber) | |
182 | { | |
183 | BitFont *CurrentFont; | |
184 | ||
185 | CurrentFont = DT_FontPointer(FontNumber); | |
186 | if(CurrentFont) | |
187 | return CurrentFont->CharWidth; | |
188 | else | |
189 | return 0; | |
190 | } | |
191 | ||
192 | /* Returns a pointer to the font struct of the number | |
193 | * returns NULL if theres an error | |
194 | */ | |
195 | BitFont *DT_FontPointer(int FontNumber) | |
196 | { | |
197 | BitFont *CurrentFont = BitFonts; | |
198 | BitFont *temp; | |
199 | ||
200 | while(CurrentFont) | |
201 | if(CurrentFont->FontNumber == FontNumber) | |
202 | return CurrentFont; | |
203 | else | |
204 | { | |
205 | temp = CurrentFont; | |
206 | CurrentFont = CurrentFont->NextFont; | |
207 | } | |
208 | ||
209 | return NULL; | |
210 | ||
211 | } | |
212 | ||
213 | /* removes all the fonts currently loaded */ | |
214 | void DT_DestroyDrawText() | |
215 | { | |
216 | BitFont *CurrentFont = BitFonts; | |
217 | BitFont *temp; | |
218 | ||
219 | while(CurrentFont) | |
220 | { | |
221 | temp = CurrentFont; | |
222 | CurrentFont = CurrentFont->NextFont; | |
223 | ||
224 | SDL_FreeSurface(temp->FontSurface); | |
225 | free(temp); | |
226 | } | |
227 | ||
228 | BitFonts = NULL; | |
229 | } | |
230 | ||
231 |
0 | #ifndef Drawtext_h | |
1 | #define Drawtext_h | |
2 | ||
3 | ||
4 | #define TRANS_FONT 1 | |
5 | ||
6 | ||
7 | #ifdef __cplusplus | |
8 | extern "C" { | |
9 | #endif | |
10 | ||
11 | typedef struct BitFont_td | |
12 | { | |
13 | SDL_Surface *FontSurface; | |
14 | int CharWidth; | |
15 | int CharHeight; | |
16 | int FontNumber; | |
17 | struct BitFont_td *NextFont; | |
18 | } BitFont; | |
19 | ||
20 | ||
21 | void DT_DrawText(const char *string, SDL_Surface *surface, int FontType, int x, int y ); | |
22 | int DT_LoadFont(const char *BitmapName, int flags ); | |
23 | int DT_FontHeight( int FontNumber ); | |
24 | int DT_FontWidth( int FontNumber ); | |
25 | BitFont* DT_FontPointer(int FontNumber ); | |
26 | void DT_DestroyDrawText(); | |
27 | ||
28 | ||
29 | #ifdef __cplusplus | |
30 | }; | |
31 | #endif | |
32 | ||
33 | #endif | |
34 | ||
35 | ||
36 |
0 | #Makefile for the SDL_Console library | |
1 | ||
2 | INCLUDE = `sdl-config --cflags` -lSDL_image | |
3 | CC = gcc | |
4 | C = CON_console.c CON_consolecommands.c DT_drawtext.c internal.c | |
5 | OBJS = CON_console.o CON_consolecommands.o DT_drawtext.o internal.o | |
6 | CFLAGS = -O2 | |
7 | ||
8 | prefix = $(DEST)/usr | |
9 | libdir = $(prefix)/lib | |
10 | incdir = $(prefix)/include/SDL | |
11 | ||
12 | all: libSDL_console.so libSDL_console.a | |
13 | ||
14 | libSDL_console.so: | |
15 | $(CC) -c $(C) -fPIC $(INCLUDE) | |
16 | $(CC) -fPIC -shared $(OBJS) -o libSDL_console.so $(INCLUDE) | |
17 | ||
18 | libSDL_console.a: $(OBJS) | |
19 | ar cru libSDL_console.a $(OBJS) | |
20 | ||
21 | install: | |
22 | install -d $(libdir) | |
23 | install -d $(incdir) | |
24 | install libSDL_console.so $(libdir) | |
25 | install libSDL_console.a $(libdir) | |
26 | install CON_console.h $(incdir) | |
27 | install DT_drawtext.h $(incdir) | |
28 | ||
29 | uninstall: | |
30 | rm -f $(libdir)libSDL_console.so | |
31 | rm -f $(incdir)/CON_console.h | |
32 | rm -f $(incdir)/DT_drawtext.h | |
33 | ||
34 | clean: | |
35 | rm -f $(OBJ) libSDL_console.so libSDL_console.a core $(OBJS) | |
36 |
0 | <html> | |
1 | <head> | |
2 | <title>SDL Console</title> | |
3 | </HEAD> | |
4 | ||
5 | <body link="#0000FF" vlink="#551A8B" alink="#FF0000"> | |
6 | ||
7 | <center><h1>SDL Console</h1></center> | |
8 | ||
9 | <br><br><b>Author:</b> <a href="mailto:talanthyr@tuxfamily.org">Boris Lesner</a> | |
10 | <br><b>Original project by:</b> <a href="mailto:mongoose@mongeese.org">Garrett Banuk</a><br><br> | |
11 | ||
12 | <strong>Description:</strong><br> | |
13 | This is a console that can be added to any SDL application. It | |
14 | is similar to Quake and other game consoles but with lots of added | |
15 | features. A console is meant to be a very simple way of interacting | |
16 | with a program and executing commands. Commands are linked to the | |
17 | console with callback functions so that when a command is typed | |
18 | in, a specific function is executed automatically. | |
19 | <br>SDL_Console is released under GNU/LGPL licence ( see <a href="http://www.gnu.org/copyleft/lesser.html">www.gnu.org</a> for more information ) | |
20 | ||
21 | <br><br> | |
22 | <strong>Depends:</strong><br> | |
23 | SDL_console depends of the following libs :<br> | |
24 | <b>SDL</b> : <a href="http://www.libsdl.org">www.libsdl.org</a> | |
25 | <b>SDL_image</b> : <a href="http://www.libsdl.org/projects/SDL_image">http://www.libsdl.org/projects/SDL_image</a> | |
26 | ||
27 | <br><br><b>September 19, 2002</b> | |
28 | SDL_console 1.3 is released! Wacha Clemens again couldn't stop adding stuff to the code.<br> | |
29 | I has too many features and bugfixes to mention them here. For a complete list see below.<br> | |
30 | He has completely rewritten the command line and added lots of useful control keys. | |
31 | ||
32 | <br><br><b>September 13, 2002</b> | |
33 | SDL_console 1.2 is released thanks to Wacha Clemens who added a prompt, autoscrolling commandline, and buxfixes.<br> | |
34 | I also added CON_Free() which equals to CON_Destroy but without destroying text support of DT ( thanks to Paul Wighton ), CON_Destroy still in the lib for compatibility. | |
35 | ||
36 | <br><br><b>September 03, 2002</b> | |
37 | Garrett give me the SDL_console project and I hope I could add nice changes to the lib ! | |
38 | <br>But's it's already stable and I think that only a few things would be added.<br>For now I added a debian package of SDL_Console, the SDL_image support for PNG, JPG, ... images formats, and a shared library of the lib. | |
39 | <br>SDL_console is now version 1.1. | |
40 | <br> Boris Lesner. | |
41 | ||
42 | <br><br> | |
43 | <b>July 12, 2002</b> <font color="red" size="+1"><b>SDL_Console needs a new author!</b></font> I no longer have the time to work on SDL_Console with my new job and other interests and due to the popularity of SDL_Console, I do not want to let the project stagnate. I'm going to give the project away to someone else to maintain and improve as they see fit. The new author will have full control of the project and may do with it as they please. If you are interested in taking over the project, please <a href="mailto:mongoose@mongeese.org">email</a> me. Give me some information about your computer science skills, projects you've worked on, etc. After/if I get a sufficient response from interested people, I will decide who will take over the project. Thanks for all the support from everyone. I hope this project is still useful in the future. | |
44 | ||
45 | <br><br> | |
46 | <b>Nov 14, 2001</b> <a href="mailto:cort@andrew.cmu.edu">Cort Stratton</a> added a new MSVC project for the console with the new source. | |
47 | ||
48 | <br><br> | |
49 | <b>Oct 8, 2001</b> Finally an update to SDL_console! SDL_console has now reached version 1.0. I figured it's about time since there have not been any bug fixes for a while so the code is pretty solid. There are also lots of new additions to the code and a decent Makefile system now. If anyone wants to write an autoconf system though, be my guest. | |
50 | <ul> | |
51 | <li>Backward compatibilty has been completely broken. See the API below.</li> | |
52 | <li>Multiple independant consoles can be displayed on the screen. Checkout the <a href="screen3.jpg">screenshot</a>.</li> | |
53 | <li>Better Makefile system. Should be a little easier to work with now.</li> | |
54 | <li>Fixed a few performance issues.</li> | |
55 | <li>Cleaned up the code. Cutting and pasting everyones different coding styles into the source was getting messy.</li> | |
56 | </ul> | |
57 | ||
58 | <br><br> | |
59 | <b>June 12, 2001</b> <a href="mailto:slim@maya.com">Seung Chan Lim</a> Has donated a version of SDL_Console with the demo in MSVC project format. You can download it below. | |
60 | ||
61 | <br><br> | |
62 | <b>May 15, 2001</b> Now the console <i>really</i> works with OpenGL. =) Thanks to <a href="mailto:cort@andrew.cmu.edu">Cort Stratton</a> for fixing the OpenGL support. The console example source now demonstrates it's use with OpenGL. There is also the non-OpenGL sample source included in the archive. As usual there were a few cosmetic modifications and bug fixes also. | |
63 | ||
64 | ||
65 | <br><br> | |
66 | <b>Apr 29, 2001</b> I added a blinking cursor showing the current editing position due to popular demand. Ugh I didn't realize how ugly this code was. =) It's efficient, just not very neat. | |
67 | <ul> | |
68 | <li>Added a blinking cursor showing the current text position.</li> | |
69 | <li>Reorganized some of the code to be more readable.</li> | |
70 | </ul> | |
71 | ||
72 | ||
73 | <b>Feb 20, 2001</b> Thanks to <a href="mailto:pcruz@qwest.net">Patricia Cruz</a> for adding an OpenGL fix to the Console source. | |
74 | <ul> | |
75 | <li>Console now works within an OpenGL program and can be blitted to OpenGL surfaces.</li> | |
76 | </ul> | |
77 | ||
78 | <b>Nov 18, 2000</b> Lots of new changes here, mainly thanks to Lee Thomason for submitting some of them and motivating me to work on this again. | |
79 | <ul> | |
80 | <li>Naming conventions have been changed. Console commands now start with the CON_ prefix so as not to be confused with SDL_. Also the text drawing routines now start with DT_ so that they are distinguished as being seperate from the console.</li> | |
81 | <li>Console is no longer `attached' to the top of the screen, it is now a box that can be located anywhere. CON_Position(int x, int y)</li> | |
82 | <li>The console can be resized without reinitializing. CON_Resize(SDL_Rect rect)</li> | |
83 | <li>Tab completion lists all the matching commands rather than just completing with the first command it partially matches with. (Ya I know, this ones been overdue.)</li> | |
84 | <li>An option can be set to send back the command with the parameters from the user rather than just the parameters. So now multiple commands can be sent to one function and be distinguished from each other. CON_SendFullCommand(int sendOn)</li> | |
85 | <li>New command CON_Destroy() now shuts down and frees the console from the program. DT_DestroyDrawText() does the same thing for the text drawing routines.</li> | |
86 | <li>CON_SetConsoleBorder() has been removed. This is because of the new free moving console. Setting a border around the edges is much more complicated so I won't bother implementing this unless people ask for it.</li> | |
87 | <li>All of the help resources are going onto the webpage now rather than in the README file.</li> | |
88 | </ul> | |
89 | ||
90 | <b>April 16, 1999</b> | |
91 | <ul> | |
92 | <li>Scroll back buffer amount can be specified at init.</li> | |
93 | <li>PageUP PageDOWN scrolling through the buffer.</li> | |
94 | <li>Printing to the console is done with printf() similiar arguments.</li> | |
95 | <li>Tab completion of commands.</li> | |
96 | <li>Arbitrary number of commands can be added.</li> | |
97 | <li>Arbitrary number of arguments to each command from the input.</li> | |
98 | <li>Alpha blending onto the destination surface.(optional for speed)</li> | |
99 | <li>Border/Background image.(optional for speed)</li> | |
100 | <li>Any bitmap font can be used.</li> | |
101 | </ul> | |
102 | ||
103 | Also included is text and font handling routines for bitmap fonts. | |
104 | Bitmap fonts can be loaded up and text can be outputted to the surfaces | |
105 | using the different fonts. These bitmap font routines can be used seperately | |
106 | without the console. The text drawing routines are in the files DT_* | |
107 | ||
108 | <br><br><strong>Source:</strong><br> | |
109 | <a href="SDL_console-1.2.tar.gz">[Console and Example (SDL_console-1.2.tar.gz)]</a><br> | |
110 | <a href="SDL_console-1.2.zip">[Console and Example for MSVC (SDL_console-1.2.zip)]</a><br> | |
111 | <br><br>Additions and modifications are welcome.<br><a href="mailto:talanthyr@tuxfamily.org">Email</a> me if you have suggestions for other things to be added or fixes. | |
112 | ||
113 | <br><br><strong>ScreenShots:</strong><br> | |
114 | <a href="screen1.jpg">Small console</a> | |
115 | <br><a href="screen2.jpg">Stretched to half the screen</a> | |
116 | <br><a href="screen3.jpg">Multiple consoles on the same screen</a> | |
117 | ||
118 | <br> | |
119 | <br><b>Keyboard controls</b> | |
120 | <br><br> | |
121 | <table> | |
122 | <tr> | |
123 | <td>Up</td> | |
124 | <td>move command history up</td> | |
125 | </tr> | |
126 | <tr> | |
127 | <td>Down</td> | |
128 | <td>move command history down</td> | |
129 | </tr> | |
130 | <tr> | |
131 | <td>Left</td> | |
132 | <td>move cursor left</td> | |
133 | </tr> | |
134 | <tr> | |
135 | <td>Right</td> | |
136 | <td>move cursor right</td> | |
137 | </tr> | |
138 | <tr> | |
139 | <td>Ins</td> | |
140 | <td>toggle overwrite mode (you can set the two different cursor in CON_console.h)</td> | |
141 | </tr> | |
142 | <tr> | |
143 | <td>Del</td> | |
144 | <td>delete character above cursor</td> | |
145 | </tr> | |
146 | <tr> | |
147 | <td>Backspace</td> | |
148 | <td>delete character left of cursor</td> | |
149 | </td> | |
150 | <tr> | |
151 | <td>Home</td> | |
152 | <td>move cursor to begin of command</td> | |
153 | </tr> | |
154 | <tr> | |
155 | <td>End</td> | |
156 | <td>move cursor to end of command</td> | |
157 | </tr> | |
158 | <tr> | |
159 | <td>Ctrl-A</td> | |
160 | <td>same as Home</td> | |
161 | </tr> | |
162 | <tr> | |
163 | <td>Ctrl-E</td> | |
164 | <td>same as End</td> | |
165 | </tr> | |
166 | <tr> | |
167 | <td>Ctrl-C</td> | |
168 | <td>clear commandline</td> | |
169 | </tr> | |
170 | <tr> | |
171 | <td>Page-Up</td> | |
172 | <td>move history up</td> | |
173 | </tr> | |
174 | <tr> | |
175 | <td>Page-Down</td> | |
176 | <td>move history down</td> | |
177 | </tr> | |
178 | <tr> | |
179 | <td>Shift-Home</td> | |
180 | <td>move to top of history</td> | |
181 | </tr> | |
182 | <tr> | |
183 | <td>Shift-End</td> | |
184 | <td>move to end of history</td> | |
185 | </tr> | |
186 | <tr> | |
187 | <td>Ctrl-L</td> | |
188 | <td>clear history</td> | |
189 | </tr> | |
190 | </table> | |
191 | ||
192 | <br><br><strong>API:</strong><br> | |
193 | ||
194 | Heres an overview of the CONSOLE API. | |
195 | ||
196 | <br> | |
197 | <br><b>#include "CON_Console.h"</b> | |
198 | ||
199 | <br><br> | |
200 | Most of these functions take a pointer to a ConsoleInformation struct. This tells what console the function should proccess on. A new ConsoleInformation pointer is created with Con_Init(). | |
201 | ||
202 | <br><br><b>ConsoleInformation *CON_Init( char *FontName, SDL_Surface *DisplayScreen, int lines, SDL_Rect rect )</b> | |
203 | <br>Takes in a string of the path to the bitmap fontname, the surface the console will be displayed on, the number of lines in the back buffer of the console and an SDL_Rect with the x,y location and width and height. It returns a pointer to a ConsoleInformation struct, or NULL on error. | |
204 | ||
205 | <br><br><b>void CON_Events( SDL_Event *event )</b> | |
206 | <br>Send SDL events to this to be processed when the console is down. Be sure to set SDL_EnableUNICODE(1); for SDL before the commands are sent to the console so the console can interpet the commands. The events are sent to the console registered with CON_Topmost(); | |
207 | ||
208 | <br><br><b>void CON_DrawConsole( ConsoleInformation *console )</b> | |
209 | <br>Draws the console on the screen. | |
210 | ||
211 | <br><br><b>void CON_Out( ConsoleInformation *console, char *str, ... )</b> | |
212 | <br>Displays strings to the console, works just like printf() | |
213 | ||
214 | <br><br><b>void CON_CommandExecute( ConsoleInformation *console, char *BackStrings )</b> | |
215 | <br>Executes a command string passed to it. Usually only used internally by the console API. | |
216 | ||
217 | <br><br><b>void CON_AddCommand( void (*CommandCallback)(ConsoleInformation *console, char *Parameters), char *CommandWord )</b> | |
218 | <br>The first parameter of this is a pointer to a function that takes a ConsoleInformation pointer and a string pointer as a parameter. The ConsoleInformation pointer is the console the command was typed in, the string is the arguments passed to the command in the console. The second parameter of AddCommand is the string of the command (no space) the user will type into the console to call this function. | |
219 | ||
220 | <br><br><b>void CON_ListCommands( ConsoleInformation *console )</b> | |
221 | <br>Lists the commands in the console. | |
222 | ||
223 | <br><br><b>void CON_SendFullCommand( int sendOn )</b> | |
224 | <br>This sets a flag so that the command and the arguments typed in by the user are all sent to the callback function. This is helpful in that one callback function can be used for multiple different commands typed in by the user and easily distinguished. | |
225 | ||
226 | <br><br><b>int CON_Background( ConsoleInformation *console, char *image, int x, int y )</b> | |
227 | <br>Loads the file from image to the location (x,y) on the background. If this function is passed NULL for image the background is unloaded. | |
228 | ||
229 | <br><br><b>void CON_Alpha( ConsoleInformation *console, unsigned char alpha )</b> | |
230 | <br>Alpha blends the console into the background, value range is 1-200. | |
231 | If the alpha value passed is 0 alpha blending is turned off. | |
232 | ||
233 | <br><br><b>void CON_Destroy( ConsoleInformation *console )</b> | |
234 | <br>This shuts down and frees the console resources. | |
235 | ||
236 | <br><br><b>void CON_Free( ConsoleInformation *console )</b> | |
237 | <br>This shuts down and frees the console resources but not DrawText ressources. | |
238 | ||
239 | <br><br><b>void CON_SetPrompt(ConsoleInformation *console, char *string)</b> | |
240 | <br>This sets the prompt of the console <i>console</i> to <i>string</i> | |
241 | ||
242 | <br><br><b>void CON_Position( ConsoleInformation *console, int x, int y )</b> | |
243 | <br>This positions the console in the new x,y location. | |
244 | ||
245 | <br><br><b>int CON_Resize( ConsoleInformation *console, SDL_Rect rect )</b> | |
246 | <br>This takes an SDL_Rect to resize and move the console window. Use CON_Position() if you are just moving the console though as the resizing function has to reinitialize resources and so takes longer. | |
247 | ||
248 | <br><br><b>Special Keys</b> | |
249 | <br>Page_UP Page_DOWN scroll around the back buffer of the console TAB tab completes commands END goes back to the bottom of the console | |
250 | ||
251 | <br><br><br><br>Heres an overview of the DRAW TEXT API. | |
252 | ||
253 | <br><br><b>#include "SDL_DrawText.h"</b> | |
254 | ||
255 | <br><br><b>int DT_LoadFont( char *BitmapName, int flags )</b> | |
256 | <br>Loads a font from the BitmapName file and returns the | |
257 | number of the font. returns -1 as an error. Pass TRANS_FONT | |
258 | to the flags if the font is transparent. Transparent color is | |
259 | RGB(255,0,255) | |
260 | ||
261 | <br><br><b>void DT_DrawText( char *string, SDL_Surface *surface, int FontType, int x, int y )</b> | |
262 | <br>Draws text to the screen. First parameter is the text to | |
263 | draw, second is the surface to draw too, third is the font | |
264 | type to draw, last two are the x,y screen location. | |
265 | ||
266 | <br><br><b>int DT_FontHeight( int FontNumber )</b> | |
267 | <br>returns the font character height. | |
268 | ||
269 | <br><br><b>int DT_FontWidth( int FontNumber )</b> | |
270 | <br>returns the font character width. | |
271 | ||
272 | <br><br><b>void DT_DestroyDrawText( )</b> | |
273 | <br>Shuts down and frees all the resources used by the text drawing routines. | |
274 | ||
275 | <br><br><b>Demo info:</b> | |
276 | <br>In this demo the keys CTRL+[1,2,3] display the consoles 1, 2 or 3 to the screen. To select which console you want to type to press ALT+[1,2,3]. ALT+4 directs input back to the program. | |
277 | ||
278 | <br><br><a href="http://www.tuxfamily.org">TUXFAMILY</a> | |
279 | ||
280 | </body> | |
281 | </html> |
0 | SDL Console | |
1 | A console and text output routine written for SDL. | |
2 | ||
3 | Garrett Banuk | |
4 | (mongoose@mongeese.org) | |
5 | Boris Lesner | |
6 | (talanthyr@tuxfamily.org) | |
7 | Clemens Wacha | |
8 | (reflex-2000@gmx.net) | |
9 | ||
10 | http://sdlconsole.tuxfamily.org/ | |
11 | ||
12 | Please see the index.html file for info. |
Binary diff not shown
Binary diff not shown
Binary diff not shown
0 | /* This is an example of the console code for SDL | |
1 | * Garrett Banuk (mongoose@mongeese.org) | |
2 | */ | |
3 | ||
4 | #ifdef GL_DEMO | |
5 | #include <GL/glut.h> | |
6 | #endif /* GL_DEMO */ | |
7 | ||
8 | #include <stdlib.h> | |
9 | #include <string.h> | |
10 | #include "SDL.h" | |
11 | #include "CON_console.h" | |
12 | #include "DT_drawtext.h" | |
13 | #include "ConsoleExample.h" | |
14 | ||
15 | ||
16 | int MainProgram = 1; | |
17 | int TextDemo = 0; | |
18 | int LargeFont; | |
19 | ||
20 | ||
21 | ||
22 | #define CONSOLE_N 3 | |
23 | ConsoleInformation *Consoles[CONSOLE_N];/* Pointers to all the consoles */ | |
24 | int ConsoleDisplay[CONSOLE_N]; /* Bools telling if the console is displayed */ | |
25 | ||
26 | ||
27 | int main(int argc, char **argv) | |
28 | { | |
29 | SDL_Surface *Screen; | |
30 | int ticks = 0, oldticks = 0; | |
31 | int i; | |
32 | char framerate[30]; | |
33 | SDL_Rect Con_rect; | |
34 | ||
35 | ||
36 | ||
37 | /* init the graphics */ | |
38 | if(Init(&Screen, argc, argv)) | |
39 | return 1; | |
40 | ||
41 | ||
42 | /* Init the consoles */ | |
43 | Con_rect.x = Con_rect.y = 0; | |
44 | Con_rect.w = Con_rect.h = 300; | |
45 | if((Consoles[0] = CON_Init("ConsoleFont.png", Screen, 100, Con_rect)) == NULL) | |
46 | return 1; | |
47 | ||
48 | Con_rect.x = 350; | |
49 | Con_rect.y = 20; | |
50 | Con_rect.w = Con_rect.h = 200; | |
51 | if((Consoles[1] = CON_Init("ConsoleFont.png", Screen, 100, Con_rect)) == NULL) | |
52 | return 1; | |
53 | ||
54 | Con_rect.x = 340; | |
55 | Con_rect.y = 280; | |
56 | Con_rect.w = 300; | |
57 | Con_rect.h = 200; | |
58 | if((Consoles[2] = CON_Init("ConsoleFont.png", Screen, 100, Con_rect)) == NULL) | |
59 | return 1; | |
60 | ||
61 | ||
62 | /* Add some commands to the console */ | |
63 | CON_AddCommand(&KillProgram, "quit"); | |
64 | CON_AddCommand(&Echo, "echo"); | |
65 | CON_AddCommand(&DrawTextDemo, "drawtextdemo"); | |
66 | CON_AddCommand(&AlphaChange, "alpha"); | |
67 | CON_AddCommand(&AddBackground, "background"); | |
68 | CON_AddCommand(&Move, "move"); | |
69 | CON_AddCommand(&Resize, "resize"); | |
70 | CON_AddCommand(&ListCommands, "listcommands"); | |
71 | CON_AddCommand(&SetPrompt, "prompt"); | |
72 | ||
73 | CON_ListCommands(Consoles[0]); | |
74 | ||
75 | /* Heres another font for the text demo */ | |
76 | LargeFont = DT_LoadFont("LargeFont.png", 0); | |
77 | ||
78 | /* Main execution loop */ | |
79 | while(MainProgram) | |
80 | { | |
81 | ProcessEvents(); | |
82 | ||
83 | /* wipe the screen clean with a blue fill and draw the console if its down */ | |
84 | #ifdef GL_DEMO | |
85 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
86 | glMatrixMode(GL_MODELVIEW); | |
87 | glLoadIdentity(); | |
88 | glTranslatef(0.0, 0.0, -5.0); | |
89 | glutSolidTeapot(2.0); | |
90 | glFlush(); | |
91 | #else | |
92 | SDL_FillRect(Screen, NULL, 255); | |
93 | #endif /* GL_DEMO */ | |
94 | ||
95 | if(TextDemo) | |
96 | RandText(Screen); | |
97 | ||
98 | for(i=0; i<CONSOLE_N; i++) | |
99 | if(ConsoleDisplay[i]) CON_DrawConsole(Consoles[i]); | |
100 | ||
101 | /* print the framerate */ | |
102 | oldticks = ticks; | |
103 | ticks = SDL_GetTicks(); | |
104 | sprintf(framerate, "%.2f FPS", 1000.0 / (ticks - oldticks)); | |
105 | DT_DrawText(framerate, Screen, 1, 1, Screen->h - 40); | |
106 | ||
107 | #ifdef GL_DEMO | |
108 | SDL_GL_SwapBuffers(); | |
109 | #else | |
110 | SDL_Flip(Screen); | |
111 | #endif /* GL_DEMO */ | |
112 | } | |
113 | ||
114 | for(i=0; i<CONSOLE_N; i++) | |
115 | CON_Destroy(Consoles[i]); | |
116 | ||
117 | return 0; | |
118 | } | |
119 | ||
120 | #ifdef GL_DEMO | |
121 | /* SETUP_OPENGL -- initializes assorted OpenGL parameters */ | |
122 | void setup_opengl(int width, int height) | |
123 | { | |
124 | float ratio = (float)width / (float)height; | |
125 | /* lighting init */ | |
126 | GLfloat mat_diffuse[] = { 0.9, 0.9, 0.0, 1.0 }; | |
127 | GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; | |
128 | GLfloat mat_shininess[] = { 50.0 }; | |
129 | GLfloat light_position[] = { 1.0, 0.0, 5.0, 0.0 }; | |
130 | GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 }; | |
131 | ||
132 | glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); | |
133 | glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); | |
134 | glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); | |
135 | glLightfv(GL_LIGHT0, GL_POSITION, light_position); | |
136 | glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); | |
137 | glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); | |
138 | ||
139 | glEnable(GL_LIGHTING); | |
140 | glEnable(GL_LIGHT0); | |
141 | glEnable(GL_DEPTH_TEST); | |
142 | ||
143 | /* Set the clear color. */ | |
144 | glClearColor(0.0, 0.0, 1.0, 1.0); | |
145 | ||
146 | /* Setup our viewport. */ | |
147 | glViewport(0, 0, width, height); | |
148 | ||
149 | /* Change to the projection matrix and set our viewing volume. */ | |
150 | glMatrixMode(GL_PROJECTION); | |
151 | glLoadIdentity(); | |
152 | gluPerspective(60.0, ratio, 1.0, 1024.0); | |
153 | } | |
154 | #endif /* GL_DEMO */ | |
155 | ||
156 | /* Initialise the graphics */ | |
157 | int Init(SDL_Surface **Screen, int argc, char **argv) | |
158 | { | |
159 | #ifdef GL_DEMO | |
160 | int SetVideoFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_OPENGLBLIT; | |
161 | int width = 640, height = 480, depth = 24; | |
162 | #else | |
163 | int SetVideoFlags = SDL_HWSURFACE | SDL_DOUBLEBUF; | |
164 | int width = 640, height = 480, depth = 16; | |
165 | #endif /* GL_DEMO */ | |
166 | int loop; | |
167 | ||
168 | for(loop = 1; loop < argc; loop++) | |
169 | { | |
170 | if(strcmp(argv[loop], "-fullscreen") == 0) | |
171 | SetVideoFlags |= SDL_FULLSCREEN; | |
172 | else if(strcmp(argv[loop], "-width") == 0) | |
173 | width = atoi(argv[++loop]); | |
174 | else if(strcmp(argv[loop], "-height") == 0) | |
175 | height = atoi(argv[++loop]); | |
176 | else if(strcmp(argv[loop], "-bpp") == 0) | |
177 | depth = atoi(argv[++loop]); | |
178 | else if(strcmp(argv[loop], "-sw") == 0) | |
179 | SetVideoFlags |= SDL_SWSURFACE; | |
180 | ||
181 | } | |
182 | ||
183 | if(SDL_Init(SDL_INIT_VIDEO) < 0) | |
184 | { | |
185 | fprintf(stderr, "*Error* Couldn't initialize SDL: %s\n", SDL_GetError()); | |
186 | return 1; | |
187 | } | |
188 | ||
189 | #ifdef GL_DEMO | |
190 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); | |
191 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); | |
192 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); | |
193 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); | |
194 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | |
195 | #endif /* GL_DEMO */ | |
196 | ||
197 | if((*Screen = SDL_SetVideoMode(width, height, depth, SetVideoFlags)) == NULL) | |
198 | { | |
199 | fprintf(stderr, "*Error* Couldn't set %dx%dx%d video mode: %s\n", width, height, depth, SDL_GetError()); | |
200 | SDL_Quit(); | |
201 | return 1; | |
202 | } | |
203 | ||
204 | #ifdef GL_DEMO | |
205 | setup_opengl(width, height); | |
206 | #endif /* GL_DEMO */ | |
207 | ||
208 | atexit(SDL_Quit); | |
209 | return 0; | |
210 | } | |
211 | ||
212 | ||
213 | /* Processes all the incoming events | |
214 | */ | |
215 | void ProcessEvents() | |
216 | { | |
217 | SDL_Event event; | |
218 | static int console_events = 0; /* True if the console can take the events */ | |
219 | ||
220 | ||
221 | while(SDL_PollEvent(&event)) | |
222 | { | |
223 | switch(event.type) | |
224 | { | |
225 | case SDL_KEYDOWN: | |
226 | switch(event.key.keysym.sym) | |
227 | { | |
228 | case SDLK_1: | |
229 | case SDLK_2: | |
230 | case SDLK_3: | |
231 | case SDLK_4: | |
232 | if(event.key.keysym.mod & KMOD_CTRL) | |
233 | { | |
234 | if(ConsoleDisplay[event.key.keysym.sym - SDLK_1]) | |
235 | ConsoleDisplay[event.key.keysym.sym - SDLK_1] = 0; | |
236 | else | |
237 | ConsoleDisplay[event.key.keysym.sym - SDLK_1] = 1; | |
238 | break; | |
239 | } | |
240 | else if(event.key.keysym.mod & KMOD_ALT) | |
241 | { | |
242 | if((event.key.keysym.sym - SDLK_1) == CONSOLE_N) | |
243 | { | |
244 | CON_Topmost(NULL); | |
245 | console_events = 0; | |
246 | SDL_EnableUNICODE(0); | |
247 | SDL_EnableKeyRepeat(0,0); | |
248 | } | |
249 | else | |
250 | { | |
251 | CON_Topmost(Consoles[event.key.keysym.sym - SDLK_1]); | |
252 | console_events = 1; | |
253 | SDL_EnableUNICODE(1); | |
254 | SDL_EnableKeyRepeat(250,30); | |
255 | } | |
256 | break; | |
257 | } | |
258 | default: | |
259 | /* Send the event to the console */ | |
260 | if(console_events) | |
261 | CON_Events(&event); | |
262 | break; | |
263 | } | |
264 | break; | |
265 | case SDL_QUIT: | |
266 | MainProgram = 0; | |
267 | break; | |
268 | default: | |
269 | break; | |
270 | } | |
271 | } | |
272 | } | |
273 | ||
274 | /* call this to end the main loop */ | |
275 | void KillProgram(ConsoleInformation *console, char *String) | |
276 | { | |
277 | MainProgram = 0; | |
278 | } | |
279 | ||
280 | /* Prints the string you pass it into the console */ | |
281 | void Echo(ConsoleInformation *console, char *String) | |
282 | { | |
283 | CON_Out(console, "%s", String); | |
284 | } | |
285 | ||
286 | /* This function toggles the draw text demo */ | |
287 | void DrawTextDemo(ConsoleInformation *console, char *String) | |
288 | { | |
289 | if(TextDemo == 0) | |
290 | TextDemo = 1; | |
291 | else | |
292 | TextDemo = 0; | |
293 | } | |
294 | ||
295 | /* This function demonstrates the text drawing routines that | |
296 | * come with this console */ | |
297 | void RandText(SDL_Surface *Screen) | |
298 | { | |
299 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 40, Screen->h - 20); | |
300 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 100, 300); | |
301 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 200, 400); | |
302 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 20, 20); | |
303 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 0, 0); | |
304 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 300, 5); | |
305 | DT_DrawText("This is an example of the DrawText routine", Screen, 0, 600, 90); | |
306 | ||
307 | /* Now show the large font */ | |
308 | if(-1 != LargeFont) | |
309 | { | |
310 | DT_DrawText("Heres a large font (non-transparent)", Screen, LargeFont, 50, 60); | |
311 | DT_DrawText("Heres a large font (non-transparent)", Screen, LargeFont, 0, 170); | |
312 | } | |
313 | } | |
314 | ||
315 | /* lets the user change the alpha level */ | |
316 | void AlphaChange(ConsoleInformation *console, char *alpha) | |
317 | { | |
318 | CON_Alpha(console, atoi(alpha)); | |
319 | CON_Out(console, "Alpha set to %s.", alpha); | |
320 | } | |
321 | ||
322 | ||
323 | /* Adds a background image */ | |
324 | void AddBackground(ConsoleInformation *console, char *string) | |
325 | { | |
326 | int x, y; | |
327 | ||
328 | ||
329 | if(2 != sscanf(string, "%d %d", &x, &y)) | |
330 | { | |
331 | x = 0; | |
332 | y = 0; | |
333 | } | |
334 | ||
335 | if(x == -1 || y == -1) | |
336 | CON_Background(console, NULL, 0, 0); | |
337 | else | |
338 | CON_Background(console, "background.jpg", x, y); | |
339 | } | |
340 | ||
341 | /* Move the console, takes and x and a y */ | |
342 | void Move(ConsoleInformation *console, char *string) | |
343 | { | |
344 | int x, y; | |
345 | ||
346 | ||
347 | if(2 != sscanf(string, "%d %d", &x, &y)) | |
348 | { | |
349 | x = 0; | |
350 | y = 0; | |
351 | } | |
352 | ||
353 | CON_Position(console, x, y); | |
354 | } | |
355 | ||
356 | /* resizes the console window, takes and x and y, and a width and height */ | |
357 | void Resize(ConsoleInformation *console, char *string) | |
358 | { | |
359 | int x, y, w, h; | |
360 | ||
361 | SDL_Rect rect; | |
362 | if(4 != sscanf(string, "%d %d %d %d", &x, &y, &w, &h)) | |
363 | { | |
364 | CON_Out(console, "Usage: X Y Width Height"); | |
365 | return; | |
366 | } | |
367 | rect.x = x; | |
368 | rect.y = y; | |
369 | rect.w = w; | |
370 | rect.h = h; | |
371 | CON_Resize(console, rect); | |
372 | ||
373 | } | |
374 | ||
375 | /* Lists all the commands. */ | |
376 | void ListCommands(ConsoleInformation *console, char *string) | |
377 | { | |
378 | CON_ListCommands(console); | |
379 | } | |
380 | ||
381 | void SetPrompt(ConsoleInformation *console, char *string) { | |
382 | CON_SetPrompt(console, string); | |
383 | } |
0 | #ifndef ConsoleExample_h | |
1 | #define ConsoleExample_h | |
2 | ||
3 | ||
4 | int Init(SDL_Surface **Screen, int argc, char **argv); | |
5 | void ProcessEvents(); | |
6 | void KillProgram(ConsoleInformation *console, char *String); | |
7 | void Echo(ConsoleInformation *console, char *String); | |
8 | void DrawTextDemo(ConsoleInformation *console, char *String); | |
9 | void RandText(SDL_Surface *Screen); | |
10 | void AlphaChange(ConsoleInformation *console, char *alpha); | |
11 | void AddBackground(ConsoleInformation *console, char *string); | |
12 | void Move(ConsoleInformation *console, char *string); | |
13 | void Resize(ConsoleInformation *console, char *string); | |
14 | void ListCommands(ConsoleInformation *console, char *string); | |
15 | void SetPrompt(ConsoleInformation *console, char *string); | |
16 | ||
17 | #endif | |
18 | ||
19 | ||
20 |
Binary diff not shown
Binary diff not shown
0 | # Makefile for the SDL_Console example | |
1 | ||
2 | CC=gcc | |
3 | ||
4 | LIBS=-L.. `sdl-config --libs` -lm -lSDL_console -lSDL_image | |
5 | LIBSSTATIC=-L.. `sdl-config --libs` -lm -lSDL_image ../libSDL_console.a | |
6 | GLLIBS=$(LIBS) -lGL -lGLU -lglut | |
7 | ||
8 | FLAGS=-Wall -g -O2 | |
9 | ||
10 | INCLUDE=`sdl-config --cflags` -I.. -I. | |
11 | GLINCLUDE=$(INCLUDE) -DGL_DEMO | |
12 | ||
13 | OBJS=ConsoleExample.o | |
14 | GLOBJS=ConsoleExampleGL.o | |
15 | ||
16 | TARGET=ConsoleExample | |
17 | GLTARGET=ConsoleExampleGL | |
18 | STATIC=ConsoleExample-static | |
19 | ||
20 | SUBDIRS=.. | |
21 | ||
22 | ||
23 | all: $(TARGET) $(GLTARGET) $(STATIC) FORCE | |
24 | .PHONY: all | |
25 | ||
26 | $(SUBDIRS): FORCE | |
27 | @$(MAKE) -C $@ | |
28 | ||
29 | SUBDIRS_CLEAN = $(SUBDIRS:%=%/clean) | |
30 | $(SUBDIRS_CLEAN): FORCE | |
31 | @$(MAKE) `basename $@` -C `dirname $@` | |
32 | .PHONY: $(SUBDIRS_CLEAN) | |
33 | ||
34 | $(TARGET): $(SUBDIRS) $(OBJS) | |
35 | $(CC) $(OBJS) $(FLAGS) $(INCLUDE) $(LIBS) -o $@ | |
36 | ||
37 | $(STATIC): $(SUBDIRS) $(OBJS) | |
38 | $(CC) $(OBJS) $(FLAGS) $(INCLUDE) $(LIBSSTATIC) -o $@ | |
39 | ||
40 | %.o: %.c | |
41 | $(CC) $(FLAGS) $(INCLUDE) -c $< -o $@ | |
42 | ||
43 | %GL.o: %.c | |
44 | $(CC) $(FLAGS) $(GLINCLUDE) -c $< -o $@ | |
45 | ||
46 | $(GLTARGET): $(SUBDIRS) $(GLOBJS) | |
47 | $(CC) $(FLAGS) $(GLOBJS) $(GLLIBS) -o $@ | |
48 | ||
49 | clean: $(SUBDIRS_CLEAN) FORCE | |
50 | $(RM) core $(TARGET) $(GLTARGET) $(STATIC) $(OBJS) $(GLOBJS) | |
51 | .PHONY: clean | |
52 | ||
53 | FORCE: | |
54 | .PHONY: FORCE | |
55 | ||
56 |
Binary diff not shown
0 | /* internal.c | |
1 | * Written By: Garrett Banuk <mongoose@mongeese.org> | |
2 | * This is free, just be sure to give me credit when using it | |
3 | * in any of your programs. | |
4 | */ | |
5 | ||
6 | /* internal.[c,h] are various routines used internally | |
7 | * by SDL_console and DrawText. */ | |
8 | ||
9 | #include "SDL.h" | |
10 | ||
11 | ||
12 | /* | |
13 | * Return the pixel value at (x, y) | |
14 | * NOTE: The surface must be locked before calling this! | |
15 | */ | |
16 | Uint32 DT_GetPixel(SDL_Surface *surface, int x, int y) | |
17 | { | |
18 | int bpp = surface->format->BytesPerPixel; | |
19 | /* Here p is the address to the pixel we want to retrieve */ | |
20 | Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp; | |
21 | ||
22 | switch (bpp) | |
23 | { | |
24 | case 1: | |
25 | return *p; | |
26 | case 2: | |
27 | return *(Uint16 *) p; | |
28 | case 3: | |
29 | if(SDL_BYTEORDER == SDL_BIG_ENDIAN) | |
30 | return p[0] << 16 | p[1] << 8 | p[2]; | |
31 | else | |
32 | return p[0] | p[1] << 8 | p[2] << 16; | |
33 | case 4: | |
34 | return *(Uint32 *) p; | |
35 | default: | |
36 | return 0; /* shouldn't happen, but avoids warnings */ | |
37 | } | |
38 | } | |
39 | ||
40 | /* | |
41 | * Set the pixel at (x, y) to the given value | |
42 | * NOTE: The surface must be locked before calling this! | |
43 | */ | |
44 | void DT_PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel) | |
45 | { | |
46 | int bpp = surface->format->BytesPerPixel; | |
47 | /* Here p is the address to the pixel we want to set */ | |
48 | Uint8 *p = (Uint8 *) surface->pixels + y * surface->pitch + x * bpp; | |
49 | ||
50 | switch (bpp) | |
51 | { | |
52 | case 1: | |
53 | *p = pixel; | |
54 | break; | |
55 | case 2: | |
56 | *(Uint16 *) p = pixel; | |
57 | break; | |
58 | case 3: | |
59 | if(SDL_BYTEORDER == SDL_BIG_ENDIAN) | |
60 | { | |
61 | p[0] = (pixel >> 16) & 0xff; | |
62 | p[1] = (pixel >> 8) & 0xff; | |
63 | p[2] = pixel & 0xff; | |
64 | } | |
65 | else | |
66 | { | |
67 | p[0] = pixel & 0xff; | |
68 | p[1] = (pixel >> 8) & 0xff; | |
69 | p[2] = (pixel >> 16) & 0xff; | |
70 | } | |
71 | break; | |
72 | case 4: | |
73 | *(Uint32 *) p = pixel; | |
74 | break; | |
75 | default: | |
76 | break; | |
77 | } | |
78 | } | |
79 | ||
80 | ||
81 |
0 | #ifndef _internal_h_ | |
1 | #define _internal_h_ | |
2 | ||
3 | ||
4 | #define PRINT_ERROR(X) fprintf(stderr, "ERROR in %s:%s(): %s\n", __FILE__, __FUNCTION__, X) | |
5 | ||
6 | Uint32 DT_GetPixel(SDL_Surface *surface, int x, int y); | |
7 | void DT_PutPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); | |
8 | ||
9 | ||
10 | #endif /* _internal_h_ */ | |
11 | ||
12 |