예제 #1
0
int    GLUI_TextBox::mouse_down_handler( int local_x, int local_y )
{
  int tmp_insertion_pt;

  if ( debug )    dump( stdout, "-> MOUSE DOWN" );

  tmp_insertion_pt = find_insertion_pt( local_x, local_y );  
  if ( tmp_insertion_pt == -1 ) {
    if ( glui )
      glui->deactivate_current_control(  );
    return false;
  }

  insertion_pt = tmp_insertion_pt;

  sel_start = sel_end = insertion_pt;
 
  keygoal_x = insert_x;

  if ( can_draw())
    update_and_draw_text();

  if ( debug )    dump( stdout, "<- MOUSE UP" );

  return true;
}
예제 #2
0
int    GLUI_EditText::mouse_held_down_handler( int local_x, int local_y,
					       bool new_inside)
{
  int tmp_pt;

  if ( NOT new_inside ) 
    return false;

  if ( debug )    dump( stdout, "-> HELD DOWN" );
  
  tmp_pt = find_insertion_pt( local_x, local_y );
  
  if ( tmp_pt == -1 AND sel_end != 0 ) {    /* moved mouse past left edge */
    special_handler( GLUT_KEY_LEFT, GLUT_ACTIVE_SHIFT );
  }
  else if ( tmp_pt == substring_end+1 AND sel_end != (int) text.length()) {    
    /* moved mouse past right edge */
    special_handler( GLUT_KEY_RIGHT, GLUT_ACTIVE_SHIFT );    
  }
  else if ( tmp_pt != -1 AND tmp_pt != sel_end ) {
    sel_end = insertion_pt = tmp_pt;
    
    update_and_draw_text();
  }

  if ( debug )
    dump( stdout, "<- HELD DOWN" );

  return false;
}
예제 #3
0
int    GLUI_List::key_handler( unsigned char key,int modifiers )
{


  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;

  return true;
}
예제 #4
0
int    GLUI_EditText::special_handler( int key,int modifiers )
{
  if ( NOT glui )
    return false;
  
  if ( debug )
    printf( "SPECIAL:%d - mod:%d   subs:%d/%d  ins:%d  sel:%d/%d\n", 
	    key, modifiers, substring_start, substring_end,insertion_pt,
	    sel_start, sel_end );	 

  if ( key == GLUT_KEY_LEFT ) {
    if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
      insertion_pt = find_word_break( insertion_pt, -1 );
    }
    else {
      insertion_pt--;
    }
  }
  else if ( key == GLUT_KEY_RIGHT ) {
    if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
      insertion_pt = find_word_break( insertion_pt, +1 );
    }
    else {
      insertion_pt++;
    }
  }
  else if ( key == GLUT_KEY_HOME ) {
    insertion_pt = 0;
  }
  else if ( key == GLUT_KEY_END ) {
    insertion_pt = (int) text.length();
  }

  /*** Update selection if shift key is down ***/
  if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 )
    sel_end = insertion_pt;
  else 
    sel_start = sel_end = insertion_pt;
  

  CLAMP( insertion_pt, 0, (int) text.length()); /* Make sure insertion_pt 
						                                      is in bounds */
  CLAMP( sel_start, 0, (int) text.length()); /* Make sure insertion_pt 
						                                    is in bounds */
  CLAMP( sel_end, 0, (int) text.length()); /* Make sure insertion_pt 
					                                     is in bounds */
					      
  /******** Now redraw text ***********/
  if ( can_draw())
    update_and_draw_text();

  return true;
}
예제 #5
0
void    GLUI_CommandLine::recall_history( int hist_num )
{
  if (hist_num < oldest_hist OR
      hist_num > newest_hist OR
      hist_num == curr_hist)
    return;

  // Commit the current text first before we blow it away!
  if (curr_hist == newest_hist) {
    get_history_str(newest_hist) = text;
  }

  curr_hist = hist_num;
  set_text(get_history_str(curr_hist));
  sel_end = sel_start = insertion_pt = (int)text.length();
  update_and_draw_text();
}
예제 #6
0
void    GLUI_TextBox::set_text( const char *new_text )
{
  text = new_text;

  substring_start = 0;
  substring_end   = text.length() - 1;
  insertion_pt    = -1;
  sel_start       = 0;
  sel_end         = 0;
  visible_lines   = 0;
  start_line      = 0;
  curr_line       = 0;
  num_lines       = 0;

  if ( can_draw() )
    update_and_draw_text();

  /*** Now update the live variable ***/
  output_live(true);
}
예제 #7
0
/****************************** GLUI_List::mouse_down_handler() **********/
int    GLUI_List::mouse_down_handler( int local_x, int local_y )
{
  int tmp_line;
  unsigned long int ms;
  timeb time;
  ftime(&time);
  ms = time.millitm + (time.time)*1000;

  tmp_line = find_line( local_x-x_abs, local_y-y_abs-5 );  
  if ( tmp_line == -1 ) {
    if ( glui )
      glui->deactivate_current_control(  );
    return false;
  }

  if (tmp_line < num_lines) {
    curr_line = tmp_line;
    if (scrollbar)
      scrollbar->set_int_val(curr_line);
    this->execute_callback();
    if (associated_object != NULL)
      if (cb_click_type == GLUI_SINGLE_CLICK) {
        if (obj_cb) {
          // obj_cb(associated_object, user_id);
          obj_cb(this);
        }
      } else {
        if (last_line == curr_line && (ms - last_click_time) < 300) {
          //obj_cb(associated_object, user_id);
          obj_cb(this);
        } else {
          last_click_time = ms;
          last_line = curr_line;
        }
      }
    if ( can_draw())
      update_and_draw_text();
  }

  return true;
}
void    GLUI_EditText::set_text( char *new_text )
{
  strncpy(text,new_text,sizeof(GLUI_String));
  substring_start = 0;
  substring_end   = (int)strlen( text ) - 1;
  insertion_pt    = -1;
  sel_start       = 0;
  sel_end         = 0;

  if ( can_draw() )
    update_and_draw_text();

  /** Update the spinner, if we have one **/
  if ( spinner ) {
    spinner->float_val = this->float_val;
    spinner->int_val   = this->int_val;
  }

  /*** Now update the live variable ***/
  output_live(true);
}
예제 #9
0
void    GLUI_EditText::set_text( const char *new_text )
{
  text=new_text;
  substring_start = 0;
  substring_end   = (int) text.length() - 1;
  insertion_pt    = -1;
  sel_start       = 0;
  sel_end         = 0;

  if ( can_draw() )
    update_and_draw_text();

  /** Update the spinner, if we have one **/
  if ( spinner ) {
    spinner->float_val = this->float_val;
    spinner->int_val   = this->int_val;
  }

  /*** Now update the live variable ***/
  output_live(true);
}
예제 #10
0
int    GLUI_EditText::key_handler( unsigned char key,int modifiers )
{
  int i, regular_key;
  /* int has_selection;              */

  if ( NOT glui )
    return false;

  if ( debug )
    dump( stdout, "-> KEY HANDLER" );

  regular_key = false;
  bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0;
  /*  has_selection = (sel_start != sel_end);              */

  if ( key == CTRL('m') ) {           /* RETURN */
    /*    glui->deactivate_current_control();              */
    deactivate();  /** Force callbacks, etc **/
    activate(GLUI_ACTIVATE_TAB);     /** Reselect all text **/
    redraw();
    return true;
  }
  else if ( key  == CTRL('[')) {         /* ESCAPE */
    glui->deactivate_current_control();
    return true;
  }
  else if ( (key == 127 AND !ctrl_down) OR  /* FORWARD DELETE */
            ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) 
  {
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt < (int)text.length() ) {
        /*** See if we're deleting a period in a float data-type box ***/
        if ( ((data_type == GLUI_EDITTEXT_FLOAT) OR (data_type == GLUI_EDITTEXT_DOUBLE)) AND text[insertion_pt]=='.' )
          num_periods--;

        /*** Shift over string first ***/
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( ((key == 127) AND ctrl_down) OR   // Delete word forward
            ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) )
  {
    if ( sel_start == sel_end ) {   /* no selection */
      sel_start = insertion_pt;
      sel_end = find_word_break( insertion_pt, +1 );
    }

    clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
    insertion_pt = MIN(sel_start,sel_end);
    sel_start = sel_end = insertion_pt;
  }
  else if ( key == CTRL('h') ) {       /* BACKSPACE */
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt > 0 ) {
        /*** See if we're deleting a period in a float data-type box ***/
        if ( ((data_type == GLUI_EDITTEXT_FLOAT) OR (data_type == GLUI_EDITTEXT_DOUBLE)) AND text[insertion_pt-1]=='.' )
          num_periods--;

        /*** Shift over string first ***/
        insertion_pt--;
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( modifiers == GLUT_ACTIVE_CTRL )  /* CTRL ONLY */ 
  {
    /* Ctrl-key bindings */
    if ( key == CTRL('a') ) {
      return special_handler( GLUT_KEY_HOME, 0 );
    }
    else if ( key == CTRL('e') ) {
      return special_handler( GLUT_KEY_END, 0 );
    }
    else if ( key == CTRL('b') ) {
      return special_handler( GLUT_KEY_LEFT, 0 );
    }
    else if ( key == CTRL('f') ) {
      return special_handler( GLUT_KEY_RIGHT, 0 );
    }
    else if ( key == CTRL('p') ) {
      return special_handler( GLUT_KEY_UP, 0 );
    }
    else if ( key == CTRL('n') ) {
      return special_handler( GLUT_KEY_DOWN, 0 );
    }
    else if ( key == CTRL('u') ) { /* ERASE LINE */
      insertion_pt = 0;  
      text.erase(0,text.length());
      sel_start = sel_end = 0;
    }
    else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */
      sel_start = sel_end = insertion_pt;
      text.erase(insertion_pt,GLUI_String::npos);
    }
  }
  else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */
  {
    if ( key == 'b' ) { // Backward word
      return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL );
    }
    if ( key == 'f' ) { // Forward word
      return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL );
    }
  }
  else if ( (modifiers & GLUT_ACTIVE_CTRL) OR
            (modifiers & GLUT_ACTIVE_ALT) ) 
  {
    /** ignore other keys with modifiers */
    return true;
  }
  else { /* Regular key */    
    regular_key = true;

    /** Check if we only accept numbers **/
    if ((data_type == GLUI_EDITTEXT_FLOAT ) OR (data_type == GLUI_EDITTEXT_DOUBLE)) {
      if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' )
        return true;

      if ( key == '-' ) { /* User typed a '-' */

        /* If user has first character selected, then '-' is allowed */
        if ( NOT ( MIN(sel_start,sel_end) == 0 AND
                   MAX(sel_start,sel_end) > 0 ) ) {

          /* User does not have 1st char selected */
          if (insertion_pt != 0 OR text[0] == '-' ) {
            return true; /* Can only place negative at beginning of text,
                            and only one of them */
          }
        }
      }

      if ( key == '.' ) {
        /*printf( "PERIOD: %d\n", num_periods );              */

        if ( num_periods > 0 ) {
          /** We're trying to type a period, but the text already contains
          a period.  Check whether the period is contained within
          is current selection (thus it will be safely replaced) **/

          int period_found = false; 
          if ( sel_start != sel_end ) {
            for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) {
              /*  printf( "%c ", text[i] );              */
              if ( text[i] == '.' ) {
                period_found = true;
                break;
              }
            }
          }

          /* printf( "found: %d    num: %d\n", period_found, num_periods );              */

          if ( NOT period_found )
            return true;
        }
      }
    } 
    else if (data_type == GLUI_EDITTEXT_INT)	
    {
      if ( (key < '0' OR key > '9') AND key != '-' )
        return true;

      if ( key == '-' ) { /* User typed a '-' */

        /* If user has first character selected, then '-' is allowed */
        if ( NOT ( MIN(sel_start,sel_end) == 0 AND
          MAX(sel_start,sel_end) > 0 ) ) {

            /* User does not have 1st char selected */
            if (insertion_pt != 0 OR text[0] == '-' ) {
              return true; /* Can only place negative at beginning of text,
                           and only one of them */
            }
          }
      }
    }

    /** This is just to get rid of warnings - the flag regular_key is 
      set if the key was not a backspace, return, whatever.  But I
      believe if we're here, we know it was a regular key anyway */
    if ( regular_key ) {
    }

    /**** If there's a current selection, erase it ******/
    if ( sel_start != sel_end ) {
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }

    /******** We insert the character into the string ***/

    text.insert(insertion_pt,1,key);

    /******** Move the insertion point and substring_end one over ******/
    insertion_pt++;
    substring_end++;

    sel_start = sel_end = insertion_pt;
  }

  /******** Now redraw text ***********/
  /* Hack to prevent text box from being cleared first **/  
  /**  int substring_change =  update_substring_bounds();
  draw_text_only = 
  (NOT substring_change AND NOT has_selection AND regular_key ); 
  */

  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;


  if ( debug )
    dump( stdout, "<- KEY HANDLER" );

  /*** Now look to see if this string has a period ***/
  num_periods = 0;
  for( i=0; i<(int)text.length(); i++ )
    if ( text[i] == '.' )
      num_periods++;

  return true;
}
int    GLUI_EditText::key_handler( unsigned char key,int modifiers )
{
  int i, regular_key;
  /* int has_selection;              */

  if ( NOT glui )
    return false;

  if ( debug )
    dump( stdout, "-> KEY HANDLER" );

  regular_key = false;
  /*  has_selection = (sel_start != sel_end);              */

  if ( key == 21 AND (modifiers & GLUT_ACTIVE_CTRL )!=0) { /* DEL all text */
    /** This one (key==21) may not port!! */
    
    insertion_pt = -1;  
    text[0] = '\0';
    sel_start = sel_end = -1;
  }
  else if ( key == 13 ) {           /* RETURN */
    /*    glui->disactivate_current_control();              */
    disactivate();  /** Force callbacks, etc **/
    activate(GLUI_ACTIVATE_TAB);     /** Reselect all text **/
    translate_and_draw_front();
    return true;
  }
  else if ( key  == 27 ) {         /* ESCAPE */
    glui->disactivate_current_control();
    return true;
  }
  else if ( key == 8 ) {       /* BACKSPACE */
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt > 0 ) {
	/*** See if we're deleting a period in a float data-type box ***/
	if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt-1]=='.' )
	  num_periods--;
	
	/*** Shift over string first ***/
	insertion_pt--;
	for( i=insertion_pt; i< (int)strlen( text ); i++ )
	  text[i] = text[i+1];    
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else {                      /* Regular key */    
    regular_key = true;
    
    /** Check if we only accept numbers **/
    if (data_type == GLUI_EDITTEXT_FLOAT ) {
      if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' )
	return true;

      if ( key == '-' ) { /* User typed a '-' */

	/* If user has first character selected, then '-' is allowed */
	if ( NOT ( MIN(sel_start,sel_end) == 0 AND
		   MAX(sel_start,sel_end) > 0 ) ) {

	  /* User does not have 1st char selected */
	  if (insertion_pt != 0 OR text[0] == '-' ) {
	    return true; /* Can only place negative at beginning of text,
			    and only one of them */
	  }
	}
      }

      if ( key == '.' ) {
	/*printf( "PERIOD: %d\n", num_periods );              */

	if ( num_periods > 0 ) {
	  /** We're trying to type a period, but the text already contains
	    a period.  Check whether the period is contained within
	    is current selection (thus it will be safely replaced) **/

	  int period_found = false; 
	  if ( sel_start != sel_end ) {
	    for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) {
	      /*  printf( "%c ", text[i] );              */
	      if ( text[i] == '.' ) {
		period_found = true;
		break;
	      }
	    }
	  }

	  /* printf( "found: %d    num: %d\n", period_found, num_periods );              */
	  
	  if ( NOT period_found )
	    return true;
	}
      }
    } 
    else if (data_type == GLUI_EDITTEXT_INT)	
    {
      if ( (key < '0' OR key > '9') AND key != '-' )
	return true;

      if ( key == '-' ) { /* User typed a '-' */

	/* If user has first character selected, then '-' is allowed */
	if ( NOT ( MIN(sel_start,sel_end) == 0 AND
		   MAX(sel_start,sel_end) > 0 ) ) {

	  /* User does not have 1st char selected */
	  if (insertion_pt != 0 OR text[0] == '-' ) {
	    return true; /* Can only place negative at beginning of text,
			    and only one of them */
	  }
	}
      }
    }

    /** This is just to get rid of warnings - the flag regular_key is 
      set if the key was not a backspace, return, whatever.  But I
      believe if we're here, we know it was a regular key anyway */
    if ( regular_key ) {
    }

    /**** If there's a current selection, erase it ******/
    if ( sel_start != sel_end ) {
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }

    /******** check whether we have space ******/
    if ( (int)strlen( text ) + 2 >= sizeof( GLUI_String ))
      return false;

    /******** We insert the character into the string ***/
     
    /*** Shift over string first ***/
    for( i=(int)strlen( text ); i >= insertion_pt; i-- )
      text[i+1] = text[i];
    
    /******** Now insert the character ********/
    text[insertion_pt] = key;    

    /******** Move the insertion point and substring_end one over ******/
    insertion_pt++;
    substring_end++;

    sel_start = sel_end = insertion_pt;
  }
  
  /******** Now redraw text ***********/
  /* Hack to prevent text box from being cleared first **/  
  /**  int substring_change =  update_substring_bounds();
    draw_text_only = 
    (NOT substring_change AND NOT has_selection AND regular_key ); 
    */

  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;


  if ( debug )
    dump( stdout, "<- KEY HANDLER" );

  /*** Now look to see if this string has a period ***/
  num_periods = 0;
  for( i=0; i<(int)strlen(text); i++ )
    if ( text[i] == '.' )
      num_periods++;

  return true;
}
예제 #12
0
int    GLUI_TextBox::special_handler( int key,int modifiers )
{
  int tmp_insertion_pt;
  if ( NOT glui )
    return false;

  if ( debug )
    printf( "SPECIAL:%d - mod:%d   subs:%d/%d  ins:%d  sel:%d/%d\n", 
        key, modifiers, substring_start, substring_end,insertion_pt,
        sel_start, sel_end );    

  if ( key == GLUT_KEY_DOWN ) {
    if (insert_x == -1 || insert_y == -1)
      return false;
    tmp_insertion_pt = find_insertion_pt( keygoal_x, insert_y+LINE_HEIGHT);
    if (tmp_insertion_pt < 0)
      return false;
    insertion_pt = tmp_insertion_pt;
    sel_end = insertion_pt;
    if (!(modifiers & GLUT_ACTIVE_SHIFT)) {
      sel_start = sel_end;
    }
    if ( can_draw())
      update_and_draw_text();    
  } else if ( key == GLUT_KEY_UP ) {
    if (insert_x == -1 || insert_y == -1)
      return false;
    tmp_insertion_pt = find_insertion_pt( keygoal_x, insert_y-LINE_HEIGHT);  
    if (tmp_insertion_pt < 0)
      return false;
    insertion_pt = tmp_insertion_pt;
    sel_end = insertion_pt;
    if (!(modifiers & GLUT_ACTIVE_SHIFT)) {
      sel_start = sel_end;
    }
    if ( can_draw())
      update_and_draw_text();    
  } else if ( key == GLUT_KEY_LEFT ) {
    if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
      insertion_pt = find_word_break( insertion_pt, -1 );
    }
    else {
      insertion_pt--;
    }
    // update keygoal_x!
  }
  else if ( key == GLUT_KEY_RIGHT ) {
    if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) {
      insertion_pt = find_word_break( insertion_pt, +1 );
    }
    else {
      insertion_pt++;
    }
    // update keygoal_x!
  }
  else if ( key == GLUT_KEY_HOME ) {
    insertion_pt = 0;
    // update keygoal_x!
  }
  else if ( key == GLUT_KEY_END ) {
    insertion_pt = text.length();
    // update keygoal_x!
  }

  /*** Update selection if shift key is down ***/
  if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 )
    sel_end = insertion_pt;
  else 
    sel_start = sel_end = insertion_pt;
  

  CLAMP( insertion_pt, 0, (int)text.length()); /* Make sure insertion_pt 
                           is in bounds */
  CLAMP( sel_start, 0, (int)text.length()); /* Make sure insertion_pt 
                        is in bounds */
  CLAMP( sel_end, 0, (int)text.length()); /* Make sure insertion_pt 
                          is in bounds */

  /******** Now redraw text ***********/
  if ( can_draw())
    update_and_draw_text();

  return true;
}
예제 #13
0
/****************************** GLUI_TextBox::key_handler() **********/
int    GLUI_TextBox::key_handler( unsigned char key,int modifiers )
{
  /* int has_selection;              */

  if ( NOT glui )
    return false;

  if ( debug )
    dump( stdout, "-> KEY HANDLER" );

  bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0;
  /*  has_selection = (sel_start != sel_end);              */

  if ( key  == CTRL('[')) {         /* ESCAPE */
    glui->deactivate_current_control();
    return true;
  }
  else if ( (key == 127 AND !ctrl_down) OR  /* FORWARD DELETE */
            ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) 
  {
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt < (int)text.length() ) {
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( ((key == 127) AND ctrl_down) OR   // Delete word forward
            ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) )
  {
    if ( sel_start == sel_end ) {   /* no selection */
      sel_start = insertion_pt;
      sel_end = find_word_break( insertion_pt, +1 );
    }

    clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
    insertion_pt = MIN(sel_start,sel_end);
    sel_start = sel_end = insertion_pt;
  }
  else if ( key == CTRL('h') ) {       /* BACKSPACE */
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt > 0 ) {
        insertion_pt--;
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( modifiers == GLUT_ACTIVE_CTRL )  /* CTRL ONLY */ 
  {
    /* Ctrl-key bindings */
    if ( key == CTRL('a') ) {
      return special_handler( GLUT_KEY_HOME, 0 );
    }
    else if ( key == CTRL('e') ) {
      return special_handler( GLUT_KEY_END, 0 );
    }
    else if ( key == CTRL('b') ) {
      return special_handler( GLUT_KEY_LEFT, 0 );
    }
    else if ( key == CTRL('f') ) {
      return special_handler( GLUT_KEY_RIGHT, 0 );
    }
    else if ( key == CTRL('p') ) {
      return special_handler( GLUT_KEY_UP, 0 );
    }
    else if ( key == CTRL('n') ) {
      return special_handler( GLUT_KEY_DOWN, 0 );
    }
    else if ( key == CTRL('u') ) { /* ERASE LINE */
      insertion_pt = 0;  
      text.erase(0,text.length());
      sel_start = sel_end = 0;
    }
    else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */
      sel_start = sel_end = insertion_pt;
      text.erase(insertion_pt,GLUI_String::npos);
    }
  }
  else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */
  {
    if ( key == 'b' ) { // Backward word
      return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL );
    }
    if ( key == 'f' ) { // Forward word
      return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL );
    }
  }
  else if ( (modifiers & GLUT_ACTIVE_CTRL) OR
            (modifiers & GLUT_ACTIVE_ALT) ) 
  {
    /** ignore other keys with modifiers */
    return true;
  }
  else { /* Regular key */    
    if ( key == 13 )           /* RETURNS are written as newlines*/
      key = '\n';

    /**** If there's a current selection, erase it ******/
    if ( sel_start != sel_end ) {
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }

    /******** We insert the character into the string ***/

    text.insert(insertion_pt,1,key);

    /******** Move the insertion point and substring_end one over ******/
    insertion_pt++;
    substring_end++;

    sel_start = sel_end = insertion_pt;
  }

  /******** Now redraw text ***********/
  /* Hack to prevent text box from being cleared first **/  
  /**  int substring_change =  update_substring_bounds();
       draw_text_only = 
       (NOT substring_change AND NOT has_selection AND regular_key ); 
  */

  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;


  if ( debug )
    dump( stdout, "<- KEY HANDLER" );

  return true;
}