/* test_text_in.c  test inputting text in OpenGL textbox */
/*                 uses text_in.c which uses GLUT        */

#include <stdio.h>
#include <string.h>
#include <GL/glut.h>

static int getting_text = 0;
static char * the_text;
static void (*text_entered)();

static char user_input[100] = "";
static color_file_entry_window = 0;
static char more_input[20] = "";
static char position_text[100] = "init";

static void open_a_file(char filename[])
{
  printf("open a file named %s\n", filename);
  color_file_entry_window = 0;
}

static void convert_int(char user_text[])
{
  int i;
  
  i = atoi(user_text);
  printf("user text converted to integer i=%d\n", i);
}

static void clear_text(char msg[])
{
  msg[0]='\0';
}

static void get_text(char msg[], void (*call_with_text)())
{
  getting_text = 1;
  the_text = msg;
  text_entered = call_with_text;
}

static int add_text(unsigned char key)
{
  char msg[] = "x";
  int len;
  
  if(!getting_text) return 0;
  if(key==8) /* backspace */
  {
    len = strlen(the_text);
    the_text[len-1] = '\0';
  }
  else if(key==13 || key==9)
  {
    getting_text = 0;
    text_entered(the_text);
  }
  else
  {
    msg[0] = key;
    strcat(the_text, msg);
  }
  glutPostRedisplay();
  return 1;
}

static void stop_text(char msg[])
{
  getting_text = 0;
}

static void show_text(GLfloat x, GLfloat y, char msg[])
{
  int len, i;

  glPushMatrix();
    glRasterPos2f(x, y);
    len = strlen(msg);
    for (i = 0; i<len; i++)
      glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, msg[i]);
  glPopMatrix();
} /* end show_text */

static void display(void)
{
  /* display callback, clear frame buffer and z buffer, */
  /* rotate split_cube and draw, swap buffers */
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();
  
  /* just as with any graphics object, user must color or light */
  /* x, y  are relative to current coordinate transformations   */
  glLoadIdentity();
  /* draw rectangle where text will be */
  glBegin(GL_POLYGON);
    glColor3f(0.7, 0.7, 0.7);
    if(color_file_entry_window) glColor3f(0.3, 1.0, 0.3);
    glVertex2f(-0.5,  0.5);
    glVertex2f(-0.5, -0.5);
    glVertex2f( 8.0, -0.5);
    glVertex2f( 8.0,  0.5);
  glEnd();
  glColor3f(0.0, 0.0, 0.0);
  show_text(-0.5, -1.0, "user input, file name");
  glColor3f(0.0, 0.0, 0.0);
  show_text(0.0, -.25, user_input);

  glLoadIdentity();
  /* draw rectangle where text will be */
  glBegin(GL_POLYGON);
    glColor3f(0.8, 0.8, 0.8);
    glVertex2f(-0.5, -4.5);
    glVertex2f(-0.5, -5.5);
    glVertex2f( 8.0, -5.5);
    glVertex2f( 8.0, -4.5);
  glEnd();
  glColor3f(0.0, 0.0, 0.0);
  show_text(0.0, -6.25, "type an integer");
  glColor3f(0.0, 0.0, 0.0);
  show_text(0.0, -5.25, more_input);

  glLoadIdentity();
  /* draw rectangle where text will be */
  glBegin(GL_POLYGON);
    glColor3f(0.8, 0.8, 0.8);
    glVertex2f(-9.5, 9.5);
    glVertex2f(-9.5, 8.5);
    glVertex2f(-3.0, 8.5);
    glVertex2f(-3.0, 9.5);
  glEnd();
  glColor3f(0.0, 0.0, 0.0);
  show_text(-9.5, 8.0, "type with pointer in box");
  glColor3f(0.0, 0.0, 0.0);
  show_text(-9.0, 8.75, position_text);

  glLoadIdentity();
  glColor3f(1.0, 0.0, 0.0);
  show_text(-3.0, -9.0, "right mouse for menu");

  glFlush();
  glutSwapBuffers();
} /* end display */


static void mouse(int btn, int state, int x, int y)
{
  /* mouse callback, selects an axis about which to rotate */
  if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) ;
  /* if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) for menu */
  glutPostRedisplay();
} /* end mouse */

static void keyboard(unsigned char key, int x, int y)
{
  char astr[] = "x";
  
  printf("user key=%c, keyval=%d at x=%d, y=%d \n", key, key, x, y);
  if(x<200 && y<50) /* top left of screen */
  {
    astr[0] = key;
    strcat(position_text, astr);
    glutPostRedisplay();
    return;
  }

  if(add_text(key)) return; /* activated by call to get_text() */
  
  switch (key)
  {
    case 'a': /* do something with keys not captured */
      break;
    default :
      break;
  }
  glutPostRedisplay();
} /* end keyboard */

static void special(int k, int x, int y)
{
  switch(k)
  {
    case GLUT_KEY_LEFT:
      break;
    case GLUT_KEY_RIGHT:
      break;
    case GLUT_KEY_DOWN:
      break;
    case GLUT_KEY_UP:
      break;
  }
  glutPostRedisplay();
}

static void myReshape(int w, int h)
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if(w <= h)
      glOrtho(-10.0, 10.0, -10.0 * (GLfloat)h / (GLfloat)w,
              10.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);
  else
      glOrtho(-10.0 * (GLfloat)w / (GLfloat)h,
              10.0 * (GLfloat)w / (GLfloat)h, -10.0, 10.0, -10.0, 10.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
} /* end myReshape */


void menu_action(int id)
{
  if(id==0)
  {
    color_file_entry_window = 1;
    clear_text(user_input);
    get_text(user_input, open_a_file);
  }
  else if(id==1)
  {
    clear_text(more_input);
    get_text(more_input, convert_int);
  }
  else if(id==2) exit(0);
  glutPostRedisplay();
}

static void init()
{
}

int main(int argc, char *argv[])
{
  glutInitDisplayMode(GLUT_DOUBLE);
  glutInitWindowSize(400, 400);
  glutInitWindowPosition(100, 100);
  glutCreateWindow(argv[0]);
  glutReshapeFunc(myReshape);      /* enable resize/reshape */
  glutDisplayFunc(display);        /* enable display */
  glutMouseFunc(mouse);            /* enable mouse */
  glutKeyboardFunc(keyboard);      /* enable keyboard */
  glutSpecialFunc(special);        /* enable arrow keys */
  glutCreateMenu(menu_action);     /* enable menu */
  glutAddMenuEntry("open file", 0);
  glutAddMenuEntry("enter number", 1);
  glutAddMenuEntry("quit", 2);
  glutAttachMenu(GLUT_RIGHT_BUTTON);

  init();
  glutMainLoop();
  return 0;
} /* end text_text_in.c */

