demo-console.c 22.1 KB
Newer Older
1
/* ============================================================================
2 3 4
 * Freetype GL - A C OpenGL Freetype engine
 * Platform:    Any
 * WWW:         http://code.google.com/p/freetype-gl/
5 6
 * ----------------------------------------------------------------------------
 * Copyright 2011,2012 Nicolas P. Rougier. All rights reserved.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * The views and conclusions contained in the software and documentation are
 * those of the authors and should not be interpreted as representing official
 * policies, either expressed or implied, of Nicolas P. Rougier.
 * ========================================================================= */
33 34 35
#include <wchar.h>
#include <string.h>
#include <stdio.h>
36 37 38 39 40 41
#include "freetype-gl.h"
#include "vertex-buffer.h"
#include "markup.h"
#include "shader.h"
#include "mat4.h"

42 43 44 45 46 47 48 49
#if defined(__APPLE__)
    #include <Glut/glut.h>
#elif defined(_WIN32) || defined(_WIN64)
    #include <GLUT/glut.h>
#else
    #include <GL/glut.h>
#endif

50

51 52 53 54
#if defined(_WIN32) || defined(_WIN64)
#  define wcpncpy wcsncpy
#  define wcpcpy  wcscpy
#endif
55

56

57 58 59 60 61 62 63 64 65
// -------------------------------------------------------------- constants ---
const int __SIGNAL_ACTIVATE__     = 0;
const int __SIGNAL_COMPLETE__     = 1;
const int __SIGNAL_HISTORY_NEXT__ = 2;
const int __SIGNAL_HISTORY_PREV__ = 3;
#define MAX_LINE_LENGTH  511


const int MARKUP_NORMAL      = 0;
66 67 68 69 70 71 72 73 74
const int MARKUP_DEFAULT     = 0;
const int MARKUP_ERROR       = 1;
const int MARKUP_WARNING     = 2;
const int MARKUP_OUTPUT      = 3;
const int MARKUP_BOLD        = 4;
const int MARKUP_ITALIC      = 5;
const int MARKUP_BOLD_ITALIC = 6;
const int MARKUP_FAINT       = 7;
#define   MARKUP_COUNT         8
75 76 77


// ------------------------------------------------------- typedef & struct ---
78 79 80 81 82 83 84 85
typedef struct {
    float x, y, z;
    float s, t;
    float r, g, b, a;
} vertex_t;

struct _console_t {
    vector_t *     lines;
86 87 88 89
    wchar_t *      prompt;
    wchar_t        killring[MAX_LINE_LENGTH+1];
    wchar_t        input[MAX_LINE_LENGTH+1];
    size_t         cursor;
90 91 92 93
    markup_t       markup[MARKUP_COUNT];
    vertex_buffer_t * buffer;
    vec2           pen; 
    void (*handlers[4])( struct _console_t *, wchar_t * );
94
};
95
typedef struct _console_t console_t;
96 97 98


// ------------------------------------------------------- global variables ---
99
static console_t * console;
100
GLuint shader;
101
mat4   model, view, projection;
102 103


104
// ------------------------------------------------------------ console_new ---
105
console_t *
106
console_new( void )
107
{
108
    console_t *self = (console_t *) malloc( sizeof(console_t) );
109
    if( !self )
110
    {
111
        return self;
112
    }
113 114 115
    self->lines = vector_new( sizeof(wchar_t *) );
    self->prompt = (wchar_t *) wcsdup( L">>> " );
    self->cursor = 0;
116
    self->buffer = vertex_buffer_new( "vertex:3f,tex_coord:2f,color:4f" );
117 118 119 120 121 122
    self->input[0] = L'\0';
    self->killring[0] = L'\0';
    self->handlers[__SIGNAL_ACTIVATE__]     = 0;
    self->handlers[__SIGNAL_COMPLETE__]     = 0;
    self->handlers[__SIGNAL_HISTORY_NEXT__] = 0;
    self->handlers[__SIGNAL_HISTORY_PREV__] = 0;
123 124 125 126
    self->pen.x = self->pen.y = 0;

    texture_atlas_t * atlas = texture_atlas_new( 512, 512, 1 );
 
127 128 129
    vec4 white = {{1,1,1,1}};
    vec4 black = {{0,0,0,1}};
    vec4 none = {{0,0,1,0}};
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

    markup_t normal;
    normal.family  = "fonts/VeraMono.ttf";
    normal.size    = 13.0;
    normal.bold    = 0;
    normal.italic  = 0;
    normal.rise    = 0.0;
    normal.spacing = 0.0;
    normal.gamma   = 1.0;
    normal.foreground_color    = black;
    normal.background_color    = none;
    normal.underline           = 0;
    normal.underline_color     = white;
    normal.overline            = 0;
    normal.overline_color      = white;
    normal.strikethrough       = 0;
    normal.strikethrough_color = white;
147

148
    normal.font = texture_font_new_from_file( atlas, 13, "fonts/VeraMono.ttf" );
149 150 151

    markup_t bold = normal;
    bold.bold = 1;
152
    bold.font = texture_font_new_from_file( atlas, 13, "fonts/VeraMoBd.ttf" );
153 154 155

    markup_t italic = normal;
    italic.italic = 1;
156
    bold.font = texture_font_new_from_file( atlas, 13, "fonts/VeraMoIt.ttf" );
157 158 159 160

    markup_t bold_italic = normal;
    bold.bold = 1;
    italic.italic = 1;
161
    italic.font = texture_font_new_from_file( atlas, 13, "fonts/VeraMoBI.ttf" );
162 163

    markup_t faint = normal;
164 165 166
    faint.foreground_color.r = 0.35;
    faint.foreground_color.g = 0.35;
    faint.foreground_color.b = 0.35;
167 168

    markup_t error = normal;
169 170 171
    error.foreground_color.r = 1.00;
    error.foreground_color.g = 0.00;
    error.foreground_color.b = 0.00;
172 173

    markup_t warning = normal;
174 175 176
    warning.foreground_color.r = 1.00;
    warning.foreground_color.g = 0.50;
    warning.foreground_color.b = 0.50;
177 178

    markup_t output = normal;
179 180 181
    output.foreground_color.r = 0.00;
    output.foreground_color.g = 0.00;
    output.foreground_color.b = 1.00;
182 183 184 185 186 187 188 189

    self->markup[MARKUP_NORMAL] = normal;
    self->markup[MARKUP_ERROR] = error;
    self->markup[MARKUP_WARNING] = warning;
    self->markup[MARKUP_OUTPUT] = output;
    self->markup[MARKUP_FAINT] = faint;
    self->markup[MARKUP_BOLD] = bold;
    self->markup[MARKUP_ITALIC] = italic;
190 191 192 193 194 195 196
    self->markup[MARKUP_BOLD_ITALIC] = bold_italic;

    return self;
}



197
// -------------------------------------------------------- console_delete ---
198
void
199
console_delete( console_t *self )
200 201 202 203
{ }



204
// ----------------------------------------------------- console_add_glyph ---
205
void
206
console_add_glyph( console_t *self,
207 208
                   wchar_t current,
                   wchar_t previous,
209
                   markup_t *markup )
210
{
211
    texture_glyph_t *glyph  = texture_font_get_glyph( markup->font, current );
212 213 214 215
    if( previous != L'\0' )
    {
        self->pen.x += texture_glyph_get_kerning( glyph, previous );
    }
216 217 218 219
    float r = markup->foreground_color.r;
    float g = markup->foreground_color.g;
    float b = markup->foreground_color.b;
    float a = markup->foreground_color.a;
220 221 222 223
    int x0  = self->pen.x + glyph->offset_x;
    int y0  = self->pen.y + glyph->offset_y;
    int x1  = x0 + glyph->width;
    int y1  = y0 - glyph->height;
224 225 226 227
    float s0 = glyph->s0;
    float t0 = glyph->t0;
    float s1 = glyph->s1;
    float t1 = glyph->t1;
228

229
    GLuint indices[] = {0,1,2, 0,2,3};
230 231 232 233
    vertex_t vertices[] = { { x0,y0,0,  s0,t0,  r,g,b,a },
                            { x0,y1,0,  s0,t1,  r,g,b,a },
                            { x1,y1,0,  s1,t1,  r,g,b,a },
                            { x1,y0,0,  s1,t0,  r,g,b,a } };
234 235
    vertex_buffer_push_back( self->buffer, vertices, 4, indices, 6 );
    
236 237 238 239 240 241
    self->pen.x += glyph->advance_x;
    self->pen.y += glyph->advance_y;
}



242
// -------------------------------------------------------- console_render ---
243
void
244
console_render( console_t *self )
245 246 247 248 249 250
{
    int viewport[4];
    glGetIntegerv( GL_VIEWPORT, viewport );

    size_t i, index;
    self->pen.x = 0;
251
    self->pen.y = viewport[3];
252
    vertex_buffer_clear( console->buffer );
253 254 255 256

    int cursor_x = self->pen.x;
    int cursor_y = self->pen.y;

257
    markup_t markup;
258

259
    // console_t buffer
260
    markup = self->markup[MARKUP_FAINT];
261 262
    self->pen.y -= markup.font->height;

263 264 265 266 267
    for( i=0; i<self->lines->size; ++i )
    {
        wchar_t *text = * (wchar_t **) vector_get( self->lines, i ) ;
        if( wcslen(text) > 0 )
        {
268
            console_add_glyph( console, text[0], L'\0', &markup );
269 270
            for( index=1; index < wcslen(text)-1; ++index )
            {
271
                console_add_glyph( console, text[index], text[index-1], &markup );
272 273
            }
        }
274
        self->pen.y -= markup.font->height - markup.font->linegap;
275 276 277 278 279 280 281 282 283
        self->pen.x = 0;
        cursor_x = self->pen.x;
        cursor_y = self->pen.y;
    }

    // Prompt
    markup = self->markup[MARKUP_BOLD];
    if( wcslen( self->prompt ) > 0 )
    {
284
        console_add_glyph( console, self->prompt[0], L'\0', &markup );
285 286
        for( index=1; index < wcslen(self->prompt); ++index )
        {
287
            console_add_glyph( console, self->prompt[index], self->prompt[index-1], &markup );
288 289 290 291 292 293 294 295
        }
    }
    cursor_x = (int) self->pen.x;

    // Input
    markup = self->markup[MARKUP_NORMAL];
    if( wcslen(self->input) > 0 )
    {
296
        console_add_glyph( console, self->input[0], L'\0', &markup );
297 298 299 300 301 302
        if( self->cursor > 0)
        {
            cursor_x = (int) self->pen.x;
        }
        for( index=1; index < wcslen(self->input); ++index )
        {
303
            console_add_glyph( console, self->input[index], self->input[index-1], &markup );
304 305 306 307 308 309 310
            if( index < self->cursor )
            {
                cursor_x = (int) self->pen.x;
            }
        }
    }

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
    // Cursor (we use the black character (-1) as texture )
    texture_glyph_t *glyph  = texture_font_get_glyph( markup.font, -1 );
    float r = markup.foreground_color.r;
    float g = markup.foreground_color.g;
    float b = markup.foreground_color.b;
    float a = markup.foreground_color.a;
    int x0  = cursor_x+1;
    int y0  = cursor_y + markup.font->descender;
    int x1  = cursor_x+2;
    int y1  = y0 + markup.font->height - markup.font->linegap;
    float s0 = glyph->s0;
    float t0 = glyph->t0;
    float s1 = glyph->s1;
    float t1 = glyph->t1;
    GLuint indices[] = {0,1,2, 0,2,3};
    vertex_t vertices[] = { { x0,y0,0,  s0,t0,  r,g,b,a },
                            { x0,y1,0,  s0,t1,  r,g,b,a },
                            { x1,y1,0,  s1,t1,  r,g,b,a },
                            { x1,y0,0,  s1,t0,  r,g,b,a } };
    vertex_buffer_push_back( self->buffer, vertices, 4, indices, 6 );
331
    glEnable( GL_TEXTURE_2D );
332

333
    glUseProgram( shader );
334 335 336 337 338 339 340 341 342 343 344 345 346
    {
        glUniform1i( glGetUniformLocation( shader, "texture" ),
                     0 );
        glUniformMatrix4fv( glGetUniformLocation( shader, "model" ),
                            1, 0, model.data);
        glUniformMatrix4fv( glGetUniformLocation( shader, "view" ),
                            1, 0, view.data);
        glUniformMatrix4fv( glGetUniformLocation( shader, "projection" ),
                            1, 0, projection.data);
        vertex_buffer_render( console->buffer, GL_TRIANGLES );
    }


347 348 349 350
}



351
// ------------------------------------------------------- console_connect ---
352
void
353
console_connect( console_t *self,
354
                  const char *signal,
355
                  void (*handler)(console_t *, wchar_t *))
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
{
    if( strcmp( signal,"activate" ) == 0 )
    {
        self->handlers[__SIGNAL_ACTIVATE__] = handler;
    }
    else if( strcmp( signal,"complete" ) == 0 )
    {
        self->handlers[__SIGNAL_COMPLETE__] = handler;
    }
    else if( strcmp( signal,"history-next" ) == 0 )
    {
        self->handlers[__SIGNAL_HISTORY_NEXT__] = handler;
    }
    else if( strcmp( signal,"history-prev" ) == 0 )
    {
        self->handlers[__SIGNAL_HISTORY_PREV__] = handler;
    }
}



377
// --------------------------------------------------------- console_print ---
378
void
379
console_print( console_t *self, wchar_t *text )
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
{
    // Make sure there is at least one line
    if( self->lines->size == 0 )
    {
        wchar_t *line = wcsdup( L"" );
        vector_push_back( self->lines, &line );
    }

    // Make sure last line does not end with '\n'
    wchar_t *last_line = *(wchar_t **) vector_get( self->lines, self->lines->size-1 ) ;
    if( wcslen( last_line ) != 0 )
    {
        if( last_line[wcslen( last_line ) - 1] == L'\n' )
        {
            wchar_t *line = wcsdup( L"" );
            vector_push_back( self->lines, &line );
        }
    }
    last_line = *(wchar_t **) vector_get( self->lines, self->lines->size-1 ) ;

    wchar_t *start = text;
    wchar_t *end   = wcschr(start, L'\n');
    size_t len = wcslen( last_line );
    if( end != NULL)
    {
        wchar_t *line = (wchar_t *) malloc( (len + end - start + 2)*sizeof( wchar_t ) );
        wcpncpy( line, last_line, len );
        wcpncpy( line + len, text, end-start+1 );

        line[len+end-start+1] = L'\0';

        vector_set( self->lines, self->lines->size-1, &line );
        free( last_line );
        if( (end-start)  < (wcslen( text )-1) )
        {
415
            console_print(self, end+1 );
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
        }
        return;
    }
    else
    {
        wchar_t *line = (wchar_t *) malloc( (len + wcslen(text) + 1) * sizeof( wchar_t ) );
        wcpncpy( line, last_line, len );
        wcpcpy( line + len, text );
        vector_set( self->lines, self->lines->size-1, &line );
        free( last_line );
        return;
    }
}



432
// ------------------------------------------------------- console_process ---
433
void
434
console_process( console_t *self,
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
                  const char *action,
                  const unsigned char key )
{
    size_t len = wcslen(self->input);

    if( strcmp(action, "type") == 0 )
    {
        if( len < MAX_LINE_LENGTH )
        {
            memmove( self->input + self->cursor+1,
                     self->input + self->cursor, 
                     (len - self->cursor+1)*sizeof(wchar_t) );
            self->input[self->cursor] = (wchar_t) key;
            self->cursor++;
        }
        else
        {
            fprintf( stderr, "Input buffer is full\n" );
        }
    }
    else
    {
        if( strcmp( action, "enter" ) == 0 )
        {
459
            if( console->handlers[__SIGNAL_ACTIVATE__] )
460
            {
461
                (*console->handlers[__SIGNAL_ACTIVATE__])(console, console->input);
462
            }
463 464 465
            console_print( self, self->prompt );
            console_print( self, self->input );
            console_print( self, L"\n" );
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
            self->input[0] = L'\0';
            self->cursor = 0;
        }
        else if( strcmp( action, "right" ) == 0 )
        {
            if( self->cursor < wcslen(self->input) )
            {
                self->cursor += 1;
            }
        }
        else if( strcmp( action, "left" ) == 0 )
        {
            if( self->cursor > 0 )
            {
                self->cursor -= 1;
            }
        }
        else if( strcmp( action, "delete" ) == 0 )
        {
            memmove( self->input + self->cursor,
                     self->input + self->cursor+1, 
                     (len - self->cursor)*sizeof(wchar_t) );
        }
        else if( strcmp( action, "backspace" ) == 0 )
        {
            if( self->cursor > 0 )
            {
                memmove( self->input + self->cursor-1,
                         self->input + self->cursor, 
                         (len - self->cursor+1)*sizeof(wchar_t) );
                self->cursor--;
            }
        }
        else if( strcmp( action, "kill" ) == 0 )
        {
            if( self->cursor < len )
            {
                wcpcpy(self->killring, self->input + self->cursor );
                self->input[self->cursor] = L'\0';
                fwprintf(stderr, L"Kill ring: %ls\n", self->killring);
            }
            
        }
        else if( strcmp( action, "yank" ) == 0 )
        {
            size_t l = wcslen(self->killring);
            if( (len + l) < MAX_LINE_LENGTH )
            {
                memmove( self->input + self->cursor + l,
                         self->input + self->cursor, 
                         (len - self->cursor)*sizeof(wchar_t) );
                memcpy( self->input + self->cursor,
                        self->killring, l*sizeof(wchar_t));
                self->cursor += l;
            }
        }
        else if( strcmp( action, "home" ) == 0 )
        {
            self->cursor = 0;
        }
        else if( strcmp( action, "end" ) == 0 )
        {
            self->cursor = wcslen( self->input );
        }
        else if( strcmp( action, "clear" ) == 0 )
        {
        }
        else if( strcmp( action, "history-prev" ) == 0 )
        {
535
            if( console->handlers[__SIGNAL_HISTORY_PREV__] )
536
            {
537
                (*console->handlers[__SIGNAL_HISTORY_PREV__])(console, console->input);
538 539 540 541
            }
        }
        else if( strcmp( action, "history-next" ) == 0 )
        {
542
            if( console->handlers[__SIGNAL_HISTORY_NEXT__] )
543
            {
544
                (*console->handlers[__SIGNAL_HISTORY_NEXT__])(console, console->input);
545 546 547 548
            }
        }
        else if( strcmp( action, "complete" ) == 0 )
        {
549
            if( console->handlers[__SIGNAL_COMPLETE__] )
550
            {
551
                (*console->handlers[__SIGNAL_COMPLETE__])(console, console->input);
552 553 554 555 556 557 558 559 560 561 562 563 564 565
            }
        }
    }
}



// ----------------------------------------------------------- on_key_press ---
void
on_key_press ( unsigned char key, int x, int y )
{
    // fprintf( stderr, "key: %d\n", key);
    if (key == 1)
    {
566
        console_process( console, "home", 0 );
567 568 569
    }
    else if (key == 4)
    { 
570
        console_process( console, "delete", 0 );
571 572 573
    }
    else if (key == 5)
    { 
574
        console_process( console, "end", 0 );
575 576 577
    }
    else if (key == 8)
    { 
578
        console_process( console, "backspace", 0 );
579 580 581
    }
    else if (key == 9)
    {
582
        console_process( console, "complete", 0 );
583 584 585
    }
    else if (key == 11)
    {
586
        console_process( console, "kill", 0 );
587 588 589
    }
    else if (key == 12)
    {
590
        console_process( console, "clear", 0 );
591 592 593
    }
    else if (key == 13)
    {
594
        console_process( console, "enter", 0 );
595 596 597
    }
    else if (key == 25)
    {
598
        console_process( console, "yank", 0 );
599 600 601
    }
    else if (key == 27)
    {
602
        console_process( console, "escape", 0 );
603 604 605
    }
    else if (key == 127)
    {
606
        console_process( console, "backspace", 0 );
607 608 609
    }
    else if( key > 31)
    {
610
        console_process( console, "type", key );
611 612 613 614 615 616 617 618 619 620 621 622 623
    }
    glutPostRedisplay();
}



// --------------------------------------------------- on_special_key_press ---
void
on_special_key_press( int key, int x, int y )
{
    switch (key)
    {
    case GLUT_KEY_UP:
624
        console_process( console, "history-prev", 0 );
625 626
        break;
    case GLUT_KEY_DOWN:
627
        console_process( console, "history-next", 0 );
628 629
        break;
    case GLUT_KEY_LEFT:
630
        console_process( console,  "left", 0 );
631 632
        break;
    case GLUT_KEY_RIGHT:
633
        console_process( console, "right", 0 );
634 635
        break;
    case GLUT_KEY_HOME:
636
        console_process( console, "home", 0 );
637 638
        break;
    case GLUT_KEY_END:
639
        console_process( console, "end", 0 );
640 641 642 643 644 645 646 647 648 649 650 651
        break;
    default:
        break;
    }
    glutPostRedisplay();
}



// ------------------------------------------------------------- on_display ---
void on_display (void) {
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
652
    console_render( console );
653 654 655 656 657 658 659 660 661
    glutSwapBuffers();
}



// ------------------------------------------------------------- on_reshape ---
void on_reshape (int width, int height)
{
    glViewport(0, 0, width, height);
662
    mat4_set_orthographic( &projection, 0, width, 0, height, -1, 1);
663 664 665 666 667 668 669 670 671 672 673
}



// ---------------------------------------------------------------- on_init ---
void on_init( void )
{
}


// ----------------------------------------------------------------------------
674
void console_activate (console_t *self, wchar_t * input)
675
{
676
    //console_print( self, L"Activate callback\n" );
677 678
    fwprintf( stderr, L"Activate callback : %ls\n", input );
}
679
void console_complete (console_t *self, wchar_t *input)
680
{
681
    // console_print( self, L"Complete callback\n" );
682 683
    fwprintf( stderr, L"Complete callback : %ls\n", input );
}
684
void console_history_prev (console_t *self, wchar_t *input)
685
{
686
    // console_print( self, L"History prev callback\n" );
687 688
    fwprintf( stderr, L"History prev callback : %ls\n", input );
}
689
void console_history_next (console_t *self, wchar_t *input)
690
{
691
    // console_print( self, L"History next callback\n" );
692 693 694 695 696 697 698 699 700
    fwprintf( stderr, L"History next callback : %ls\n", input );
}


int
main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
701
    glutCreateWindow( argv[0] );
702 703 704 705 706
    glutReshapeFunc( on_reshape );
    glutDisplayFunc( on_display );
    glutKeyboardFunc( on_key_press );
    glutSpecialFunc( on_special_key_press );
    glutReshapeWindow( 600,400 );
707
#ifndef __APPLE__
708
    glewExperimental = GL_TRUE;
709 710 711 712 713 714 715 716
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        /* Problem: glewInit failed, something is seriously wrong. */
        fprintf( stderr, "Error: %s\n", glewGetErrorString(err) );
        exit( EXIT_FAILURE );
    }
    fprintf( stderr, "Using GLEW %s\n", glewGetString(GLEW_VERSION) );
717
#endif
718 719 720 721 722 723 724 725
    console = console_new();
    console_print( console,
                   L"OpenGL Freetype console\n"
                   L"Copyright 2011 Nicolas P. Rougier. All rights reserved.\n \n" );
    console_connect( console, "activate",     console_activate );
    console_connect( console, "complete",     console_complete );
    console_connect( console, "history-prev", console_history_prev );
    console_connect( console, "history-next", console_history_next );
726

727
    glClearColor( 1.00, 1.00, 1.00, 1.00 );
728 729 730 731 732
    glDisable( GL_DEPTH_TEST ); 
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable( GL_TEXTURE_2D );
    glEnable( GL_BLEND );

733 734
    shader = shader_load("shaders/v3f-t2f-c4f.vert",
                         "shaders/v3f-t2f-c4f.frag");
735 736 737
    mat4_set_identity( &projection );
    mat4_set_identity( &model );
    mat4_set_identity( &view );
738
    glutMainLoop();
739

740

741 742
    return 0;
}