1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <SDL2/SDL_platform.h>
5 #include <SDL2/SDL_opengl.h>
6 #include <SDL2/SDL_keycode.h>
7 
8 #include <lua.h>
9 #include <lualib.h>
10 #include <lauxlib.h>
11 #include <memory.h>
12 
13 #include "utf8_32.h"
14 #include "gl_font.h"
15 #include "gl_util.h"
16 #include "console.h"
17 #include "system.h"
18 #include "vmath.h"
19 #include "gl_text.h"
20 
21 
22 static struct
23 {
24     GLfloat                     background_color[4];
25     GLfloat                     edit_font_color[4];
26 
27     uint32_t                    edit_size;
28     char                       *edit_buff;
29 
30     uint16_t                    lines_count;
31     uint16_t                    commands_count;
32     uint16_t                    lines_buff_size;
33     uint16_t                    commands_buff_size;
34     uint16_t                   *lines_styles;
35     char                      **lines_buff;
36     char                      **commands_buff;
37 
38     int                       (*exec_cmd)(char *ch);        // Exec function pointer
39 
40     uint16_t                    line_height;                // Height, including spacing
41     uint16_t                    height;                     // Console height in pixels
42 
43     float                       spacing;                    // Line spacing
44     float                       cursor_time;                // Current cursor draw time
45     float                       show_cursor_period;
46 
47     int16_t                     lines_scroll;
48     int16_t                     cursor_pos;                 // Current cursor position, in symbols
49     int16_t                     command_pos;
50     uint16_t                    show_cursor : 1;            // Cursor visibility flag
51     uint16_t                    show_console : 1;           // Visibility flag
52 } con_base;
53 
54 
55 static GLuint                   backgroundBuffer = 0;
56 static GLuint                   cursorBuffer = 0;
57 
58 static void Con_FillBackgroundBuffer();
59 static void Con_DrawBackground();
60 static void Con_DrawCursor(GLint x, GLint y);
61 static void Con_AddCommandToHistory(const char *text);
62 
Con_Init()63 void Con_Init()
64 {
65     con_base.exec_cmd = NULL;
66 
67     con_base.edit_size = 4096;
68     con_base.edit_buff = (char*)calloc(con_base.edit_size, sizeof(char));
69 
70     con_base.lines_buff_size = 128;
71     con_base.lines_buff = (char**)calloc(con_base.lines_buff_size, sizeof(char*));
72     con_base.lines_styles = (uint16_t*)calloc(con_base.lines_buff_size, sizeof(uint16_t));
73     con_base.commands_buff_size = 128;
74     con_base.commands_buff = (char**)calloc(con_base.commands_buff_size, sizeof(char*));
75 
76     con_base.lines_scroll = 0;
77     con_base.lines_count = 0;
78     con_base.commands_count = 0;
79     con_base.command_pos = 0;
80     con_base.height = 240;
81 
82     // spacing check
83     if(con_base.spacing < CON_MIN_LINE_INTERVAL)
84     {
85         con_base.spacing = CON_MIN_LINE_INTERVAL;
86     }
87     if(con_base.spacing > CON_MAX_LINE_INTERVAL)
88     {
89         con_base.spacing = CON_MAX_LINE_INTERVAL;
90     }
91 }
92 
93 
Con_SetExecFunction(int (* exec_cmd)(char * ch))94 void Con_SetExecFunction(int(*exec_cmd)(char *ch))
95 {
96     con_base.exec_cmd = exec_cmd;
97 }
98 
99 
Con_InitFont()100 void Con_InitFont()
101 {
102     qglGenBuffersARB(1, &backgroundBuffer);
103     qglGenBuffersARB(1, &cursorBuffer);
104     if(!GLText_GetFont(FONT_CONSOLE))
105     {
106         GLText_AddFont(0, 12, "resource/fonts/DroidSansMono.ttf");
107     }
108     if(GLText_GetFont(FONT_CONSOLE))
109     {
110         Con_SetLineInterval(con_base.spacing);
111     }
112     Con_FillBackgroundBuffer();
113 }
114 
115 
Con_InitGlobals()116 void Con_InitGlobals()
117 {
118     con_base.background_color[0] = 1.0f;
119     con_base.background_color[1] = 0.9f;
120     con_base.background_color[2] = 0.7f;
121     con_base.background_color[3] = 0.4f;
122 
123     con_base.edit_font_color[0] = 0.8f;
124     con_base.edit_font_color[1] = 0.9f;
125     con_base.edit_font_color[2] = 0.7f;
126     con_base.edit_font_color[3] = 1.0f;
127 
128     con_base.exec_cmd        = NULL;
129     con_base.spacing         = CON_MIN_LINE_INTERVAL;
130     con_base.height          = 240;
131 
132     con_base.show_cursor_period = 0.5f;
133     con_base.cursor_pos = 0;
134 }
135 
136 
Con_Destroy()137 void Con_Destroy()
138 {
139     if(con_base.edit_buff)
140     {
141         free(con_base.edit_buff);
142     }
143     con_base.edit_buff = NULL;
144     con_base.edit_size = 0;
145 
146     qglDeleteBuffersARB(1, &backgroundBuffer);
147     qglDeleteBuffersARB(1, &cursorBuffer);
148     backgroundBuffer = 0;
149     cursorBuffer = 0;
150 
151     con_base.lines_count = 0;
152     if(con_base.lines_buff)
153     {
154         for(uint16_t i = 0; i < con_base.lines_buff_size; ++i)
155         {
156             if(con_base.lines_buff[i])
157             {
158                 free(con_base.lines_buff[i]);
159             }
160         }
161         free(con_base.lines_buff);
162         con_base.lines_buff = NULL;
163         con_base.lines_buff_size = 0;
164     }
165 
166     con_base.commands_count = 0;
167     if(con_base.commands_buff)
168     {
169         for(uint16_t i = 0; i < con_base.commands_buff_size; ++i)
170         {
171             if(con_base.commands_buff[i])
172             {
173                 free(con_base.commands_buff[i]);
174             }
175         }
176         free(con_base.commands_buff);
177         con_base.commands_buff = NULL;
178         con_base.commands_buff_size = 0;
179     }
180 }
181 
182 
Con_GetLineInterval()183 float Con_GetLineInterval()
184 {
185     return con_base.spacing;
186 }
187 
188 
Con_SetLineInterval(float interval)189 void Con_SetLineInterval(float interval)
190 {
191     if((interval >= CON_MIN_LINE_INTERVAL) && (interval <= CON_MAX_LINE_INTERVAL))
192     {
193         gl_tex_font_p gl_font = GLText_GetFont(FONT_CONSOLE);
194         con_base.spacing = interval;
195         if(gl_font)
196         {
197             con_base.line_height = (1.0 + con_base.spacing) * gl_font->font_size;
198         }
199     }
200 }
201 
202 
Con_SetHeight(uint16_t value)203 void Con_SetHeight(uint16_t value)
204 {
205     if((value >= con_base.line_height) && (value <= screen_info.h))
206     {
207         con_base.height = value;
208         Con_FillBackgroundBuffer();
209     }
210 }
211 
212 
Con_GetHeight()213 uint16_t Con_GetHeight()
214 {
215     return con_base.height;
216 }
217 
218 
Con_SetBackgroundColor(float color[4])219 void Con_SetBackgroundColor(float color[4])
220 {
221     vec4_copy(con_base.background_color, color);
222 }
223 
224 
Con_SetShowCursorPeriod(float time)225 void Con_SetShowCursorPeriod(float time)
226 {
227     con_base.show_cursor_period = time;
228 }
229 
230 
Con_SetLinesHistorySize(uint16_t count)231 void Con_SetLinesHistorySize(uint16_t count)
232 {
233     if((count >= 16) && (count <= 32767) && (count != con_base.lines_buff_size))
234     {
235         char **new_buff = (char**)calloc(count, sizeof(char*));
236         for(uint16_t i = 0; i < con_base.lines_count; ++i)
237         {
238             if(i < count)
239             {
240                 new_buff[i] = con_base.lines_buff[i];
241             }
242             else
243             {
244                 free(con_base.lines_buff[i]);
245             }
246         }
247         free(con_base.lines_buff);
248         con_base.lines_buff = new_buff;
249         con_base.lines_buff_size = count;
250         con_base.lines_count = (con_base.lines_count < count) ? (con_base.lines_count) : (count - 1);
251     }
252 }
253 
254 
Con_SetCommandsHistorySize(uint16_t count)255 void Con_SetCommandsHistorySize(uint16_t count)
256 {
257     if((count >= 16) && (count <= 32767) && (count != con_base.commands_buff_size))
258     {
259         char **new_buff = (char**)calloc(count, sizeof(char*));
260         for(uint16_t i = 0; i < con_base.commands_count; ++i)
261         {
262             if(i < count)
263             {
264                 new_buff[i] = con_base.commands_buff[i];
265             }
266             else
267             {
268                 free(con_base.commands_buff[i]);
269             }
270         }
271         free(con_base.commands_buff);
272         con_base.commands_buff = new_buff;
273         con_base.commands_buff_size = count;
274         con_base.commands_count = (con_base.commands_count < count) ? (con_base.commands_count) : (count - 1);
275     }
276 }
277 
278 
Con_Scroll(int value)279 void Con_Scroll(int value)
280 {
281     con_base.lines_scroll += value;
282     con_base.lines_scroll = (con_base.lines_scroll < 0) ? (0) : (con_base.lines_scroll);
283 }
284 
285 
Con_Filter(char * text)286 void Con_Filter(char *text)
287 {
288     if(text)
289     {
290         uint8_t *utf8 = (uint8_t*)text;
291         uint32_t utf32;
292         while(*utf8)
293         {
294             utf8 = utf8_to_utf32(utf8, &utf32);
295             Con_Edit(utf32);
296         }
297     }
298 }
299 
300 
Con_Edit(int key)301 void Con_Edit(int key)
302 {
303     if(key == SDLK_UNKNOWN || key == SDLK_BACKQUOTE || key == SDLK_BACKSLASH)
304     {
305         return;
306     }
307 
308     if((key == SDLK_RETURN) && con_base.edit_buff)
309     {
310         Con_AddCommandToHistory(con_base.edit_buff);
311         if(con_base.exec_cmd && !con_base.exec_cmd(con_base.edit_buff))
312         {
313             Con_AddLine(con_base.edit_buff, 0);
314         }
315         con_base.edit_buff[0] = 0;
316         con_base.cursor_pos = 0;
317         con_base.command_pos = (con_base.commands_count > 0) ? (con_base.commands_count - 1) : (0);
318         return;
319     }
320 
321     con_base.cursor_time = 0.0f;
322     con_base.show_cursor = 1;
323 
324     uint32_t oldLength = utf8_strlen(con_base.edit_buff);
325 
326     switch(key)
327     {
328         case SDLK_PAGEUP:
329             Con_Scroll(1);
330             break;
331 
332         case SDLK_PAGEDOWN:
333             Con_Scroll(-1);
334             break;
335 
336         case SDLK_UP:
337             if(con_base.commands_count > 0)
338             {
339                 strncpy(con_base.edit_buff, con_base.commands_buff[con_base.command_pos], con_base.edit_size);
340                 con_base.cursor_pos = utf8_strlen(con_base.edit_buff);
341                 con_base.command_pos++;
342                 con_base.command_pos = (con_base.command_pos >= con_base.commands_count) ? (0) : (con_base.command_pos);
343             }
344             break;
345 
346         case SDLK_DOWN:
347             if(con_base.commands_count > 0)
348             {
349                 strncpy(con_base.edit_buff, con_base.commands_buff[con_base.command_pos], con_base.edit_size);
350                 con_base.cursor_pos = utf8_strlen(con_base.edit_buff);
351                 con_base.command_pos--;
352                 con_base.command_pos = (con_base.command_pos < 0) ? (con_base.commands_count - 1) : (con_base.command_pos);
353             }
354             break;
355 
356         case SDLK_LEFT:
357             if(con_base.cursor_pos > 0)
358             {
359                 con_base.cursor_pos--;
360             }
361             break;
362 
363         case SDLK_RIGHT:
364             if(con_base.cursor_pos < oldLength)
365             {
366                 con_base.cursor_pos++;
367             }
368             break;
369 
370         case SDLK_HOME:
371             con_base.cursor_pos = 0;
372             break;
373 
374         case SDLK_END:
375             con_base.cursor_pos = oldLength;
376             break;
377 
378         case SDLK_BACKSPACE:
379             if(con_base.cursor_pos > 0)
380             {
381                 con_base.cursor_pos--;
382                 utf8_delete_char((uint8_t*)con_base.edit_buff, con_base.cursor_pos);
383             }
384             break;
385 
386         case SDLK_DELETE:
387             if((con_base.cursor_pos < oldLength))
388             {
389                 utf8_delete_char((uint8_t*)con_base.edit_buff, con_base.cursor_pos);
390             }
391             break;
392 
393         default:
394             if(oldLength >= con_base.edit_size - 8)
395             {
396                 char *new_buff = (char*)calloc(con_base.edit_size * 2, sizeof(char));
397                 if(new_buff)
398                 {
399                     memcpy(new_buff, con_base.edit_buff, con_base.edit_size);
400                     con_base.edit_buff = new_buff;
401                     con_base.edit_size *= 2;
402                 }
403             }
404             if((oldLength < con_base.edit_size - 8) && (key >= SDLK_SPACE))
405             {
406                 utf8_insert_char((uint8_t*)con_base.edit_buff, key, con_base.cursor_pos, con_base.edit_size);
407                 ++oldLength;
408                 con_base.cursor_pos++;
409             }
410             break;
411     }
412 }
413 
414 
Con_AddCommandToHistory(const char * text)415 void Con_AddCommandToHistory(const char *text)
416 {
417     if(text && *text)
418     {
419         uint32_t len = strlen(text);
420         char *str = (char*)malloc((len + 1) * sizeof(char));
421         memcpy(str, text, len);
422         str[len] = 0;
423         if(con_base.commands_count + 1 < con_base.commands_buff_size)
424         {
425             con_base.commands_buff[con_base.commands_count++] = str;
426         }
427         else
428         {
429             free(con_base.commands_buff[0]);
430             for(uint16_t i = 1; i < con_base.commands_buff_size; ++i)
431             {
432                 con_base.commands_buff[i - 1] = con_base.commands_buff[i];
433             }
434             con_base.commands_buff[con_base.commands_buff_size - 1] = str;
435         }
436     }
437 }
438 
439 
Con_AddLine(const char * text,uint16_t font_style)440 void Con_AddLine(const char *text, uint16_t font_style)
441 {
442     if(text && *text)
443     {
444         uint32_t len = strlen(text);
445         char *str = (char*)malloc((len + 1) * sizeof(char));
446         memcpy(str, text, len);
447         str[len] = 0;
448         if(con_base.lines_count < con_base.lines_buff_size)
449         {
450             con_base.lines_styles[con_base.lines_count] = font_style;
451             con_base.lines_buff[con_base.lines_count++] = str;
452         }
453         else
454         {
455             free(con_base.lines_buff[0]);
456             for(uint16_t i = 1; i < con_base.lines_buff_size; ++i)
457             {
458                 con_base.lines_buff[i - 1] = con_base.lines_buff[i];
459                 con_base.lines_styles[i - 1] = con_base.lines_styles[i];
460             }
461             con_base.lines_buff[con_base.lines_buff_size - 1] = str;
462             con_base.lines_styles[con_base.lines_buff_size - 1] = font_style;
463         }
464     }
465 }
466 
467 
Con_AddText(const char * text,uint16_t font_style)468 void Con_AddText(const char *text, uint16_t font_style)
469 {
470     if(text)
471     {
472         char buf[4096], ch;
473         size_t i, j, text_size = strlen(text);
474 
475         buf[0] = 0;
476         for(i = 0, j = 0; i < text_size; i++)
477         {
478             ch = text[i];
479             if((ch == 10) || (ch == 13))
480             {
481                 j = (j < sizeof(buf)) ? (j) : (sizeof(buf) - 1);
482                 buf[j] = 0;
483                 buf[sizeof(buf) - 1] = 0;
484                 if((j > 0) && ((buf[0] != 10) && (buf[0] != 13) && ((buf[0] > 31) || (buf[1] > 32))))
485                 {
486                     Con_AddLine(buf, font_style);
487                 }
488                 j = 0;
489             }
490             else if(j < sizeof(buf) - 1)
491             {
492                buf[j++] = ch;
493             }
494         }
495 
496         buf[sizeof(buf) - 1] = 0;
497         if(j < sizeof(buf))
498         {
499             buf[j] = 0;
500         }
501         if((j > 0) && ((buf[0] != 10) && (buf[0] != 13) && ((buf[0] > 31) || (buf[1] > 32))))
502         {
503             Con_AddLine(buf, font_style);
504         }
505     }
506 }
507 
508 
Con_Printf(const char * fmt,...)509 void Con_Printf(const char *fmt, ...)
510 {
511     va_list argptr;
512     char buf[4096];
513 
514     va_start(argptr, fmt);
515     vsnprintf(buf, sizeof(buf), fmt, argptr);
516     buf[sizeof(buf) - 1] = 0;
517     va_end(argptr);
518     Con_AddLine(buf, FONTSTYLE_CONSOLE_NOTIFY);
519 }
520 
521 
Con_Warning(const char * fmt,...)522 void Con_Warning(const char *fmt, ...)
523 {
524     va_list argptr;
525     char buf[4096];
526 
527     va_start(argptr, fmt);
528     vsnprintf(buf, sizeof(buf), fmt, argptr);
529     buf[sizeof(buf) - 1] = 0;
530     va_end(argptr);
531     Con_AddLine(buf, FONTSTYLE_CONSOLE_WARNING);
532 }
533 
534 
Con_Notify(const char * fmt,...)535 void Con_Notify(const char *fmt, ...)
536 {
537     va_list argptr;
538     char buf[4096];
539 
540     va_start(argptr, fmt);
541     vsnprintf(buf, sizeof(buf), fmt, argptr);
542     buf[sizeof(buf) - 1] = 0;
543     va_end(argptr);
544     Con_AddLine(buf, FONTSTYLE_CONSOLE_NOTIFY);
545 }
546 
547 
Con_UpdateResize()548 void Con_UpdateResize()
549 {
550     Con_SetLineInterval(con_base.spacing);
551     Con_FillBackgroundBuffer();
552 }
553 
554 
Con_Clean()555 void Con_Clean()
556 {
557     for(uint16_t i = 0; i < con_base.lines_count; i++)
558     {
559         free(con_base.lines_buff[i]);
560         con_base.lines_buff[i] = NULL;
561     }
562     con_base.lines_count = 0;
563 }
564 
565 /*
566  * CONSOLE DRAW FUNCTIONS
567  */
Con_Draw(float time)568 void Con_Draw(float time)
569 {
570     gl_tex_font_p gl_font = GLText_GetFont(FONT_CONSOLE);
571     if(gl_font && con_base.show_console)
572     {
573         GLfloat y;
574         int32_t con_bottom, cursor_x = 8;
575         int32_t w_pt = (screen_info.w - 16) * 64;
576         int32_t total_chars = 0;
577         char *begin = con_base.edit_buff;
578         char *end = con_base.edit_buff;
579         int cursor_line = 0;
580         int n_sym = 0;
581         int n_lines = 1;
582 
583         con_base.height = (con_base.height > screen_info.h) ? (screen_info.h) : (con_base.height);
584 
585         for(char *ch = glf_get_string_for_width(gl_font, con_base.edit_buff, w_pt, &n_sym); *begin; ch = glf_get_string_for_width(gl_font, ch, w_pt, &n_sym))
586         {
587             n_lines += (*ch) ? (1) : (0);
588             if(con_base.cursor_pos > total_chars + n_sym)
589             {
590                 ++cursor_line;
591             }
592             else if(con_base.cursor_pos >= total_chars)
593             {
594                 cursor_x += glf_get_string_len(gl_font, begin, con_base.cursor_pos - total_chars) / 64;
595             }
596             total_chars += n_sym;
597             begin = ch;
598         }
599 
600         con_bottom = screen_info.h - con_base.height + 0.2f * (GLfloat)con_base.line_height;
601         y = (n_lines - cursor_line) * con_base.line_height - con_base.height;
602         if(y > 0)
603         {
604             con_bottom -= y;
605         }
606 
607         con_base.cursor_time += time;
608         qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
609         BindWhiteTexture();
610         Con_DrawBackground();
611         Con_DrawCursor(cursor_x, con_bottom + (n_lines - cursor_line - 1) * con_base.line_height);
612 
613         begin = con_base.edit_buff;
614         n_sym = -1;
615         for(int line = n_lines - 1; line >= 0; --line)
616         {
617             y = con_bottom + line * con_base.line_height;
618             if(n_lines > 1)
619             {
620                 end = glf_get_string_for_width(gl_font, begin, w_pt, &n_sym);
621             }
622             if(y < screen_info.h - con_base.height)
623             {
624                 break;
625             }
626             if(y < screen_info.h)
627             {
628                 vec4_copy(gl_font->gl_font_color, con_base.edit_font_color);
629                 glf_render_str(gl_font, 8, y, begin, n_sym);
630             }
631             begin = end;
632         }
633 
634         con_base.lines_scroll = (con_base.lines_scroll + 1 > con_base.lines_count) ? (con_base.lines_count - 1) : (con_base.lines_scroll);
635         con_base.lines_scroll = (con_base.lines_scroll < 0) ? (0) : (con_base.lines_scroll);
636         for(uint16_t i = con_base.lines_scroll; i < con_base.lines_count; i++)
637         {
638             char *str = con_base.lines_buff[con_base.lines_count - i - 1];
639             gl_fontstyle_p style = GLText_GetFontStyle(con_base.lines_styles[con_base.lines_count - i - 1]);
640             begin = str;
641             end = str;
642             for(char *ch = glf_get_string_for_width(gl_font, begin, w_pt, &n_sym); style && *begin; ch = glf_get_string_for_width(gl_font, ch, w_pt, &n_sym))
643             {
644                 y += con_base.line_height;
645                 if(y > screen_info.h)
646                 {
647                     return;
648                 }
649                 vec4_copy(gl_font->gl_font_color, style->font_color);
650                 glf_render_str(gl_font, 8, y, begin, n_sym);
651                 begin = ch;
652             }
653         }
654     }
655 }
656 
657 
Con_FillBackgroundBuffer()658 void Con_FillBackgroundBuffer()
659 {
660     if(backgroundBuffer)
661     {
662         GLfloat x0 = 0.0f;
663         GLfloat y0 = screen_info.h - con_base.height;
664         GLfloat x1 = screen_info.w;
665         GLfloat y1 = screen_info.h;
666         GLfloat *v, backgroundArray[32];
667 
668         v = backgroundArray;
669        *v++ = x0; *v++ = y0;
670         vec4_copy(v, con_base.background_color);
671         v += 4;
672        *v++ = 0.0f; *v++ = 0.0f;
673 
674        *v++ = x1; *v++ = y0;
675         vec4_copy(v, con_base.background_color);
676         v += 4;
677        *v++ = 1.0f; *v++ = 0.0f;
678 
679        *v++ = x1; *v++ = y1;
680         vec4_copy(v, con_base.background_color);
681         v += 4;
682        *v++ = 1.0f; *v++ = 1.0f;
683 
684        *v++ = x0; *v++ = y1;
685         vec4_copy(v, con_base.background_color);
686         v += 4;
687        *v++ = 0.0f; *v++ = 1.0f;
688         qglBindBufferARB(GL_ARRAY_BUFFER, backgroundBuffer);
689         qglBufferDataARB(GL_ARRAY_BUFFER, 32 * sizeof(GLfloat), backgroundArray, GL_STATIC_DRAW);
690     }
691 }
692 
693 
Con_DrawBackground()694 void Con_DrawBackground()
695 {
696     if(backgroundBuffer)
697     {
698         qglBindBufferARB(GL_ARRAY_BUFFER_ARB, backgroundBuffer);
699         qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)0);
700         qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));
701         qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)(6 * sizeof(GLfloat)));
702         qglDrawArrays(GL_TRIANGLE_FAN, 0, 4);
703     }
704 }
705 
706 
Con_DrawCursor(GLint x,GLint y)707 void Con_DrawCursor(GLint x, GLint y)
708 {
709     if(con_base.show_cursor_period)
710     {
711         if(con_base.cursor_time > con_base.show_cursor_period)
712         {
713             con_base.cursor_time = 0.0f;
714             con_base.show_cursor = !con_base.show_cursor;
715         }
716     }
717 
718     if(con_base.show_cursor && cursorBuffer)
719     {
720         GLfloat line_w = 1.0f;
721         GLfloat cursor_array[16];
722         GLfloat *v = cursor_array;
723 
724        *v++ = (GLfloat)x;
725        *v++ = (GLfloat)y - 0.1 * (GLfloat)con_base.line_height;
726         v[0] = 1.0; v[1] = 1.0; v[2] = 1.0; v[3] = 0.7;             v += 4;
727         v[0] = 0.0; v[1] = 0.0;                                     v += 2;
728        *v++ = (GLfloat)x;
729        *v++ = (GLfloat)y + 0.7 * (GLfloat)con_base.line_height;
730         v[0] = 1.0; v[1]= 1.0; v[2] = 1.0; v[3] = 0.7;              v += 4;
731         v[0] = 0.0; v[1] = 0.0;
732 
733         qglGetFloatv(GL_LINE_WIDTH, &line_w);
734         qglLineWidth(1.0f);
735         qglBindBufferARB(GL_ARRAY_BUFFER_ARB, cursorBuffer);
736         qglBufferDataARB(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), cursor_array, GL_DYNAMIC_DRAW);
737         qglVertexPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)0);
738         qglColorPointer(4, GL_FLOAT, 8 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat)));
739         qglTexCoordPointer(2, GL_FLOAT, 8 * sizeof(GLfloat), (void *)(6 * sizeof(GLfloat)));
740         qglDrawArrays(GL_LINES, 0, 2);
741         qglLineWidth(line_w);
742     }
743 }
744 
745 
Con_IsShown()746 int Con_IsShown()
747 {
748     return con_base.show_console;
749 }
750 
751 
Con_SetShown(int value)752 void Con_SetShown(int value)
753 {
754     con_base.show_console = value;
755 }
756