1 /**************************************************************************** 2 3 GLUI User Interface Toolkit 4 --------------------------- 5 6 glui_edittext.cpp - GLUI_EditText control class 7 8 9 -------------------------------------------------- 10 11 Copyright (c) 1998 Paul Rademacher 12 13 WWW: http://sourceforge.net/projects/glui/ 14 Forums: http://sourceforge.net/forum/?group_id=92496 15 16 This software is provided 'as-is', without any express or implied 17 warranty. In no event will the authors be held liable for any damages 18 arising from the use of this software. 19 20 Permission is granted to anyone to use this software for any purpose, 21 including commercial applications, and to alter it and redistribute it 22 freely, subject to the following restrictions: 23 24 1. The origin of this software must not be misrepresented; you must not 25 claim that you wrote the original software. If you use this software 26 in a product, an acknowledgment in the product documentation would be 27 appreciated but is not required. 28 2. Altered source versions must be plainly marked as such, and must not be 29 misrepresented as being the original software. 30 3. This notice may not be removed or altered from any source distribution. 31 32 *****************************************************************************/ 33 34 #include "glui_internal_control.h" 35 #include <cassert> 36 37 /****************************** GLUI_EditText::GLUI_EditText() **********/ 38 39 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 40 int data_type, void *live_var, 41 int id, GLUI_CB callback ) 42 { 43 if (data_type == GLUI_EDITTEXT_TEXT) { 44 live_type = GLUI_LIVE_TEXT; 45 } 46 else if (data_type == GLUI_EDITTEXT_STRING) { 47 data_type = GLUI_EDITTEXT_TEXT; // EDITTEXT_STRING doesn't really exist. 48 // Except as a signal to make a string. 49 // It's a backwards-compat hack. 50 live_type = GLUI_LIVE_STRING; 51 } 52 else if (data_type == GLUI_EDITTEXT_INT) { 53 live_type = GLUI_LIVE_INT; 54 } 55 else if (data_type == GLUI_EDITTEXT_FLOAT) { 56 live_type = GLUI_LIVE_FLOAT; 57 } 58 common_construct( parent, name, data_type, live_type, live_var, id, callback ); 59 } 60 61 /****************************** GLUI_EditText::GLUI_EditText() **********/ 62 63 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 64 int text_type, int id, GLUI_CB callback ) 65 { 66 common_construct( parent, name, text_type, GLUI_LIVE_NONE, 0, id, callback); 67 } 68 69 /****************************** GLUI_EditText::GLUI_EditText() **********/ 70 71 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 72 int *live_var, 73 int id, GLUI_CB callback ) 74 { 75 common_construct( parent, name, GLUI_EDITTEXT_INT, GLUI_LIVE_INT, live_var, id, callback); 76 } 77 78 /****************************** GLUI_EditText::GLUI_EditText() **********/ 79 80 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 81 float *live_var, 82 int id, GLUI_CB callback ) 83 { 84 common_construct( parent, name, GLUI_EDITTEXT_FLOAT, GLUI_LIVE_FLOAT, live_var, id, callback); 85 } 86 87 /****************************** GLUI_EditText::GLUI_EditText() **********/ 88 89 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 90 char *live_var, 91 int id, GLUI_CB callback ) 92 { 93 common_construct( parent, name, GLUI_EDITTEXT_TEXT, GLUI_LIVE_TEXT, live_var, id, callback); 94 } 95 96 /****************************** GLUI_EditText::GLUI_EditText() **********/ 97 98 GLUI_EditText::GLUI_EditText( GLUI_Node *parent, const char *name, 99 std::string &live_var, 100 int id, GLUI_CB callback ) 101 { 102 common_construct( parent, name, GLUI_EDITTEXT_TEXT, GLUI_LIVE_STRING, &live_var, id, callback); 103 } 104 105 /****************************** GLUI_EditText::common_construct() **********/ 106 107 void GLUI_EditText::common_construct( GLUI_Node *parent, const char *name, 108 int data_t, int live_t, void *data, int id, 109 GLUI_CB cb ) 110 { 111 common_init(); 112 set_name( name ); 113 114 live_type = live_t; 115 data_type = data_t; 116 ptr_val = data; 117 user_id = id; 118 callback = cb; 119 120 121 if ( live_type == GLUI_LIVE_INT) { 122 if ( data == NULL ) 123 set_int_val(int_val); /** Set to some default, in case of no live var **/ 124 } 125 else if ( live_type == GLUI_LIVE_FLOAT ) { 126 num_periods = 1; 127 if ( data == NULL ) 128 set_float_val(float_val); /** Set to some default, in case of no live var **/ 129 } 130 131 parent->add_control( this ); 132 133 init_live(); 134 } 135 136 /****************************** GLUI_EditText::mouse_down_handler() **********/ 137 138 int GLUI_EditText::mouse_down_handler( int local_x, int local_y ) 139 { 140 int tmp_insertion_pt; 141 142 if ( debug ) dump( stdout, "-> MOUSE DOWN" ); 143 144 tmp_insertion_pt = find_insertion_pt( local_x, local_y ); 145 if ( tmp_insertion_pt == -1 ) { 146 if ( glui ) 147 glui->deactivate_current_control( ); 148 return false; 149 } 150 151 insertion_pt = tmp_insertion_pt; 152 153 sel_start = sel_end = insertion_pt; 154 155 if ( can_draw()) 156 update_and_draw_text(); 157 158 if ( debug ) dump( stdout, "<- MOUSE UP" ); 159 160 return true; 161 } 162 163 164 /******************************** GLUI_EditText::mouse_up_handler() **********/ 165 166 int GLUI_EditText::mouse_up_handler( int local_x, int local_y, bool inside ) 167 { 168 return false; 169 } 170 171 172 /***************************** GLUI_EditText::mouse_held_down_handler() ******/ 173 174 int GLUI_EditText::mouse_held_down_handler( int local_x, int local_y, 175 bool new_inside) 176 { 177 int tmp_pt; h225rassrt_packet(void * phs,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * phi)178 179 if ( NOT new_inside ) 180 return false; 181 182 if ( debug ) dump( stdout, "-> HELD DOWN" ); 183 184 tmp_pt = find_insertion_pt( local_x, local_y ); 185 186 if ( tmp_pt == -1 AND sel_end != 0 ) { /* moved mouse past left edge */ 187 special_handler( GLUT_KEY_LEFT, GLUT_ACTIVE_SHIFT ); 188 } 189 else if ( tmp_pt == substring_end+1 AND sel_end != (int) text.length()) { 190 /* moved mouse past right edge */ 191 special_handler( GLUT_KEY_RIGHT, GLUT_ACTIVE_SHIFT ); 192 } 193 else if ( tmp_pt != -1 AND tmp_pt != sel_end ) { 194 sel_end = insertion_pt = tmp_pt; 195 196 update_and_draw_text(); 197 } 198 199 if ( debug ) 200 dump( stdout, "<- HELD DOWN" ); 201 202 return false; 203 } 204 205 206 /****************************** GLUI_EditText::key_handler() **********/ 207 208 int GLUI_EditText::key_handler( unsigned char key,int modifiers ) 209 { 210 int i, regular_key; 211 /* int has_selection; */ 212 213 if ( NOT glui ) 214 return false; 215 216 if ( debug ) 217 dump( stdout, "-> KEY HANDLER" ); 218 219 regular_key = false; 220 bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0; 221 /* has_selection = (sel_start != sel_end); */ 222 223 if ( key == CTRL('m') ) { /* RETURN */ 224 /* glui->deactivate_current_control(); */ 225 deactivate(); /** Force callbacks, etc **/ 226 activate(GLUI_ACTIVATE_TAB); /** Reselect all text **/ 227 redraw(); 228 return true; 229 } 230 else if ( key == CTRL('[')) { /* ESCAPE */ 231 glui->deactivate_current_control(); 232 return true; 233 } 234 else if ( (key == 127 AND !ctrl_down) OR /* FORWARD DELETE */ 235 ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) 236 { 237 if ( sel_start == sel_end ) { /* no selection */ 238 if ( insertion_pt < (int)text.length() ) { 239 /*** See if we're deleting a period in a float data-type box ***/ 240 if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt]=='.' ) 241 num_periods--; 242 243 /*** Shift over string first ***/ 244 text.erase(insertion_pt,1); 245 } h225ras_call_equal(gconstpointer k1,gconstpointer k2)246 } 247 else { /* There is a selection */ 248 clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); 249 insertion_pt = MIN(sel_start,sel_end); 250 sel_start = sel_end = insertion_pt; 251 } 252 } 253 else if ( ((key == 127) AND ctrl_down) OR // Delete word forward 254 ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) ) 255 { h225ras_call_hash(gconstpointer k)256 if ( sel_start == sel_end ) { /* no selection */ 257 sel_start = insertion_pt; 258 sel_end = find_word_break( insertion_pt, +1 ); 259 } 260 261 clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); 262 insertion_pt = MIN(sel_start,sel_end); 263 sel_start = sel_end = insertion_pt; find_h225ras_call(h225ras_call_info_key * h225ras_call_key,int category)264 } 265 else if ( key == CTRL('h') ) { /* BACKSPACE */ 266 if ( sel_start == sel_end ) { /* no selection */ 267 if ( insertion_pt > 0 ) { 268 /*** See if we're deleting a period in a float data-type box ***/ 269 if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt-1]=='.' ) 270 num_periods--; 271 272 /*** Shift over string first ***/ 273 insertion_pt--; 274 text.erase(insertion_pt,1); 275 } 276 } 277 else { /* There is a selection */ 278 clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); 279 insertion_pt = MIN(sel_start,sel_end); 280 sel_start = sel_end = insertion_pt; 281 } 282 } 283 else if ( modifiers == GLUT_ACTIVE_CTRL ) /* CTRL ONLY */ 284 { 285 /* Ctrl-key bindings */ 286 if ( key == CTRL('a') ) { 287 return special_handler( GLUT_KEY_HOME, 0 ); 288 } 289 else if ( key == CTRL('e') ) { 290 return special_handler( GLUT_KEY_END, 0 ); 291 } 292 else if ( key == CTRL('b') ) { 293 return special_handler( GLUT_KEY_LEFT, 0 ); 294 } 295 else if ( key == CTRL('f') ) { 296 return special_handler( GLUT_KEY_RIGHT, 0 ); 297 } 298 else if ( key == CTRL('p') ) { append_h225ras_call(h225ras_call_t * prev_call,packet_info * pinfo,e_guid_t * guid,int category _U_)299 return special_handler( GLUT_KEY_UP, 0 ); 300 } 301 else if ( key == CTRL('n') ) { 302 return special_handler( GLUT_KEY_DOWN, 0 ); 303 } 304 else if ( key == CTRL('u') ) { /* ERASE LINE */ 305 insertion_pt = 0; 306 text.erase(0,text.length()); 307 sel_start = sel_end = 0; 308 } 309 else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */ 310 sel_start = sel_end = insertion_pt; 311 text.erase(insertion_pt,GLUI_String::npos); 312 } 313 } 314 else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */ 315 { 316 if ( key == 'b' ) { // Backward word 317 return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL ); 318 } 319 if ( key == 'f' ) { // Forward word 320 return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL ); 321 } h225_frame_end(void)322 } 323 else if ( (modifiers & GLUT_ACTIVE_CTRL) OR 324 (modifiers & GLUT_ACTIVE_ALT) ) 325 { 326 /** ignore other keys with modifiers */ 327 return true; 328 } 329 else { /* Regular key */ dissect_h225_H323UserInformation(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)330 regular_key = true; 331 332 /** Check if we only accept numbers **/ 333 if (data_type == GLUI_EDITTEXT_FLOAT ) { 334 if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' ) 335 return true; 336 337 if ( key == '-' ) { /* User typed a '-' */ 338 339 /* If user has first character selected, then '-' is allowed */ 340 if ( NOT ( MIN(sel_start,sel_end) == 0 AND 341 MAX(sel_start,sel_end) > 0 ) ) { 342 343 /* User does not have 1st char selected */ 344 if (insertion_pt != 0 OR text[0] == '-' ) { 345 return true; /* Can only place negative at beginning of text, 346 and only one of them */ 347 } 348 } 349 } 350 351 if ( key == '.' ) { 352 /*printf( "PERIOD: %d\n", num_periods ); */ 353 354 if ( num_periods > 0 ) { 355 /** We're trying to type a period, but the text already contains 356 a period. Check whether the period is contained within 357 is current selection (thus it will be safely replaced) **/ 358 359 int period_found = false; 360 if ( sel_start != sel_end ) { 361 for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) { 362 /* printf( "%c ", text[i] ); */ 363 if ( text[i] == '.' ) { 364 period_found = true; 365 break; 366 } dissect_h225_h225_RasMessage(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)367 } 368 } 369 370 /* printf( "found: %d num: %d\n", period_found, num_periods ); */ 371 372 if ( NOT period_found ) 373 return true; 374 } 375 } 376 } 377 else if (data_type == GLUI_EDITTEXT_INT) 378 { 379 if ( (key < '0' OR key > '9') AND key != '-' ) 380 return true; 381 382 if ( key == '-' ) { /* User typed a '-' */ 383 384 /* If user has first character selected, then '-' is allowed */ 385 if ( NOT ( MIN(sel_start,sel_end) == 0 AND 386 MAX(sel_start,sel_end) > 0 ) ) { 387 388 /* User does not have 1st char selected */ 389 if (insertion_pt != 0 OR text[0] == '-' ) { 390 return true; /* Can only place negative at beginning of text, 391 and only one of them */ 392 } 393 } 394 } 395 } 396 397 /** This is just to get rid of warnings - the flag regular_key is 398 set if the key was not a backspace, return, whatever. But I 399 believe if we're here, we know it was a regular key anyway */ 400 if ( regular_key ) { 401 } 402 403 /**** If there's a current selection, erase it ******/ 404 if ( sel_start != sel_end ) { 405 clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end )); 406 insertion_pt = MIN(sel_start,sel_end); 407 sel_start = sel_end = insertion_pt; 408 } 409 410 /******** We insert the character into the string ***/ 411 412 text.insert(insertion_pt,1,key); 413 414 /******** Move the insertion point and substring_end one over ******/ 415 insertion_pt++; 416 substring_end++; 417 418 sel_start = sel_end = insertion_pt; 419 } 420 421 /******** Now redraw text ***********/ 422 /* Hack to prevent text box from being cleared first **/ 423 /** int substring_change = update_substring_bounds(); 424 draw_text_only = 425 (NOT substring_change AND NOT has_selection AND regular_key ); 426 */ 427 428 draw_text_only = false; /** Well, hack is not yet working **/ 429 update_and_draw_text(); 430 draw_text_only = false; 431 432 433 if ( debug ) 434 dump( stdout, "<- KEY HANDLER" ); 435 436 /*** Now look to see if this string has a period ***/ 437 num_periods = 0; 438 for( i=0; i<(int)text.length(); i++ ) 439 if ( text[i] == '.' ) 440 num_periods++; 441 442 return true; 443 } 444 445 446 /****************************** GLUI_EditText::activate() **********/ 447 448 void GLUI_EditText::activate( int how ) 449 { h225_stat_init(stat_tap_table_ui * new_stat)450 if ( debug ) 451 dump( stdout, "-> ACTIVATE" ); 452 453 active = true; 454 455 if ( how == GLUI_ACTIVATE_MOUSE ) 456 return; /* Don't select everything if activated with mouse */ 457 458 orig_text = text; 459 460 sel_start = 0; 461 sel_end = (int)text.length(); 462 insertion_pt = 0; 463 464 if ( debug ) 465 dump( stdout, "<- ACTIVATE" ); 466 } 467 468 469 /****************************** GLUI_EditText::deactivate() **********/ 470 471 void GLUI_EditText::deactivate( void ) 472 { 473 int new_int_val; 474 float new_float_val; 475 476 active = false; 477 478 if ( NOT glui ) 479 return; 480 481 if ( debug ) 482 dump( stdout, "-> DISACTIVATE" ); 483 484 sel_start = sel_end = insertion_pt = -1; 485 486 /***** Retrieve the current value from the text *****/ 487 /***** The live variable will be updated by set_text() ****/ 488 if ( data_type == GLUI_EDITTEXT_FLOAT ) { 489 if ( text.length() == 0 ) /* zero-length string - make it "0.0" */ 490 text = "0.0"; 491 492 new_float_val = atof( text.c_str() ); 493 494 set_float_val( new_float_val ); 495 } 496 else if ( data_type == GLUI_EDITTEXT_INT ) { 497 if ( text.length() == 0 ) /* zero-length string - make it "0" */ 498 text = "0"; 499 500 new_int_val = atoi( text.c_str() ); 501 502 set_int_val( new_int_val ); 503 } 504 else 505 if ( data_type == GLUI_EDITTEXT_TEXT ) { 506 set_text(text); /* This will force callbacks and gfx refresh */ 507 } 508 509 update_substring_bounds(); 510 511 /******** redraw text without insertion point ***********/ 512 redraw(); 513 514 /***** Now do callbacks if value changed ******/ 515 if ( orig_text != text ) { 516 this->execute_callback(); 517 518 if ( 0 ) { 519 /* THE CODE BELOW IS FROM WHEN SPINNER ALSO MAINTAINED CALLBACKS */ 520 if ( spinner == NULL ) { /** Are we independent of a spinner? **/ 521 if ( callback ) { 522 callback( this ); 523 } 524 } 525 else { /* We're attached to a spinner */ 526 spinner->do_callbacks(); /* Let the spinner do the callback stuff */ 527 } 528 } 529 } 530 531 if ( debug ) 532 dump( stdout, "<- DISACTIVATE" ); 533 } 534 535 /****************************** GLUI_EditText::draw() **********/ 536 537 void GLUI_EditText::draw( int x, int y ) 538 { 539 GLUI_DRAWINGSENTINAL_IDIOM 540 int name_x; 541 542 name_x = MAX(text_x_offset - string_width(this->name) - 3,0); 543 draw_name( name_x , 13); 544 545 glBegin( GL_LINES ); 546 glColor3f( .5, .5, .5 ); 547 glVertex2i( text_x_offset, 0 ); glVertex2i( w, 0 ); 548 glVertex2i( text_x_offset, 0 ); glVertex2i( text_x_offset, h ); 549 550 glColor3f( 1., 1., 1. ); 551 glVertex2i( text_x_offset, h ); glVertex2i( w, h ); 552 glVertex2i( w, h ); glVertex2i( w, 0 ); 553 554 if ( enabled ) 555 glColor3f( 0., 0., 0. ); 556 else 557 glColor3f( .25, .25, .25 ); 558 glVertex2i( text_x_offset+1, 1 ); glVertex2i( w-1, 1 ); 559 glVertex2i( text_x_offset+1, 1 ); glVertex2i( text_x_offset+1, h-1 ); 560 561 glColor3f( .75, .75, .75 ); 562 glVertex2i( text_x_offset+1, h-1 ); glVertex2i( w-1, h-1 ); 563 glVertex2i( w-1, h-1 ); glVertex2i( w-1, 1 ); 564 glEnd(); 565 566 /** Find where to draw the text **/ 567 update_substring_bounds(); 568 draw_text(0,0); 569 570 draw_insertion_pt(); 571 } 572 573 574 575 /************************** GLUI_EditText::update_substring_bounds() *********/ 576 577 int GLUI_EditText::update_substring_bounds( void ) 578 { 579 int box_width; 580 int text_len = (int)text.length(); 581 int old_start, old_end; 582 583 old_start = substring_start; 584 old_end = substring_end; 585 586 /*** Calculate the width of the usable area of the edit box ***/ 587 box_width = MAX( this->w - this->text_x_offset 588 - 4 /* 2 * the two-line box border */ 589 - 2 * GLUI_EDITTEXT_BOXINNERMARGINX, 0 ); 590 591 CLAMP( substring_end, 0, MAX(text_len-1,0) ); 592 CLAMP( substring_start, 0, MAX(text_len-1,0) ); 593 594 if ( debug ) dump( stdout, "-> UPDATE SS" ); 595 596 if ( insertion_pt >= 0 AND 597 insertion_pt < substring_start ) { /* cursor moved left */ 598 substring_start = insertion_pt; 599 600 while ( substring_width( substring_start, substring_end ) > box_width ) 601 substring_end--; 602 } 603 else if ( insertion_pt > substring_end ) { /* cursor moved right */ 604 substring_end = insertion_pt-1; 605 606 while ( substring_width( substring_start, substring_end ) > box_width ) 607 substring_start++; 608 } 609 else { /* cursor is within old substring bounds */ 610 if ( last_insertion_pt > insertion_pt ) { /* cursor moved left */ 611 } 612 else { 613 while ( substring_width( substring_start, substring_end ) > box_width ) 614 substring_end--; 615 616 while(substring_end < text_len-1 617 AND substring_width( substring_start, substring_end ) <= box_width) 618 substring_end++; 619 } 620 } 621 622 while ( substring_width( substring_start, substring_end ) > box_width ) 623 substring_end--; 624 625 last_insertion_pt = insertion_pt; 626 627 /*** No selection if not enabled ***/ 628 if ( NOT enabled ) { 629 sel_start = sel_end = 0; 630 } 631 632 if ( debug ) dump( stdout, "<- UPDATE SS" ); 633 634 if ( substring_start == old_start AND substring_end == old_end ) 635 return false; /*** bounds did not change ***/ 636 else 637 return true; /*** bounds did change ***/ 638 } 639 640 641 /********************************* GLUI_EditText::update_x_offsets() *********/ 642 643 void GLUI_EditText::update_x_offsets( void ) 644 { 645 } 646 647 648 /********************************* GLUI_EditText::draw_text() ****************/ 649 650 void GLUI_EditText::draw_text( int x, int y ) 651 { 652 GLUI_DRAWINGSENTINAL_IDIOM 653 int text_x, i, sel_lo, sel_hi; 654 655 if ( debug ) dump( stdout, "-> DRAW_TEXT" ); 656 657 if ( NOT draw_text_only ) { 658 if ( enabled ) 659 glColor3f( 1., 1., 1. ); 660 else 661 set_to_bkgd_color(); 662 glDisable( GL_CULL_FACE ); 663 glBegin( GL_QUADS ); 664 glVertex2i( text_x_offset+2, 2 ); glVertex2i( w-2, 2 ); 665 glVertex2i( w-2, h-2 ); glVertex2i( text_x_offset+2, h-2 ); 666 glEnd(); 667 } 668 669 /** Find where to draw the text **/ 670 671 text_x = text_x_offset + 2 + GLUI_EDITTEXT_BOXINNERMARGINX; 672 673 /*printf( "text_x: %d substr_width: %d start/end: %d/%d\n", 674 text_x, substring_width( substring_start, substring_end ), 675 substring_start, substring_end ); 676 */ 677 /** Find lower and upper selection bounds **/ h225_stat_packet(void * tapdata,packet_info * pinfo _U_,epan_dissect_t * edt _U_,const void * hpi_ptr)678 sel_lo = MIN(sel_start, sel_end ); 679 sel_hi = MAX(sel_start, sel_end ); 680 681 int sel_x_start, sel_x_end, delta; 682 683 /** Draw selection area dark **/ 684 if ( sel_start != sel_end ) { 685 sel_x_start = text_x; 686 sel_x_end = text_x; 687 for( i=substring_start; i<=substring_end; i++ ) { 688 delta = char_width( text[i] ); 689 690 if ( i < sel_lo ) { 691 sel_x_start += delta; 692 sel_x_end += delta; 693 } 694 else if ( i < sel_hi ) { 695 sel_x_end += delta; 696 } 697 } 698 699 glColor3f( 0.0f, 0.0f, .6f ); 700 glBegin( GL_QUADS ); 701 glVertex2i( sel_x_start, 2 ); glVertex2i( sel_x_end, 2 ); 702 glVertex2i( sel_x_end, h-2 ); glVertex2i( sel_x_start, h-2 ); 703 glEnd(); 704 } 705 706 707 if ( sel_start == sel_end ) { /* No current selection */ 708 if ( enabled ) 709 glColor3b( 0, 0, 0 ); 710 else 711 glColor3b( 32, 32, 32 ); 712 713 glRasterPos2i( text_x, 13); 714 for( i=substring_start; i<=substring_end; i++ ) { 715 glutBitmapCharacter( get_font(), this->text[i] ); 716 } 717 } 718 else { /* There is a selection */ 719 int x = text_x; 720 for( i=substring_start; i<=substring_end; i++ ) { 721 if ( IN_BOUNDS( i, sel_lo, sel_hi-1)) { /* This character is selected */ 722 glColor3f( 1., 1., 1. ); 723 glRasterPos2i( x, 13); 724 glutBitmapCharacter( get_font(), this->text[i] ); 725 } 726 else { 727 glColor3f( 0., 0., 0. ); 728 glRasterPos2i( x, 13); 729 glutBitmapCharacter( get_font(), this->text[i] ); 730 } 731 732 x += char_width( text[i] ); 733 } 734 } 735 736 if ( debug ) dump( stdout, "<- DRAW_TEXT" ); 737 } 738 739 740 /******************************** GLUI_EditText::find_insertion_pt() *********/ 741 /* This function returns the character numer *before which* the insertion */ 742 /* point goes */ 743 744 int GLUI_EditText::find_insertion_pt( int x, int y ) 745 { 746 int curr_x, i; 747 748 /*** See if we clicked outside box ***/ 749 if ( x < this->x_abs + text_x_offset ) 750 return -1; 751 752 /* We move from right to left, looking to see if the mouse was clicked 753 to the right of the ith character */ 754 755 curr_x = this->x_abs + text_x_offset 756 + substring_width( substring_start, substring_end ) 757 + 2 /* The edittext box has a 2-pixel margin */ 758 + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space 759 between the text and the box **/ 760 761 /*** See if we clicked in an empty box ***/ 762 if ( (int) text.length() == 0 ) 763 return 0; 764 765 /** find mouse click in text **/ 766 for( i=substring_end; i>=substring_start; i-- ) { 767 curr_x -= char_width( text[i] ); 768 769 if ( x > curr_x ) { 770 /* printf( "-> %d\n", i ); */ 771 772 return i+1; 773 } 774 } 775 776 return 0; 777 778 /* Well, the mouse wasn't after any of the characters...see if it's 779 before the beginning of the substring */ 780 if ( 0 ) { 781 if ( x > (x_abs + text_x_offset + 2 ) ) 782 return substring_start; 783 h225_stat_reset(stat_tap_table * table)784 return -1; /* Nothing found */ 785 } 786 } 787 788 789 /******************************** GLUI_EditText::draw_insertion_pt() *********/ 790 791 void GLUI_EditText::draw_insertion_pt( void ) 792 { 793 int curr_x, i; 794 795 if ( NOT can_draw() ) 796 return; 797 proto_register_h225(void)798 /*** Don't draw insertion pt if control is disabled ***/ 799 if ( NOT enabled ) 800 return; 801 802 if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); 803 804 if ( sel_start != sel_end OR insertion_pt < 0 ) { 805 return; /* Don't draw insertion point if there is a current selection */ 806 } 807 808 /* printf( "insertion pt: %d\n", insertion_pt ); */ 809 810 curr_x = this->x_abs + text_x_offset 811 + substring_width( substring_start, substring_end ) 812 + 2 /* The edittext box has a 2-pixel margin */ 813 + GLUI_EDITTEXT_BOXINNERMARGINX; /** plus this many pixels blank space 814 between the text and the box **/ 815 816 for( i=substring_end; i>=insertion_pt; i-- ) { 817 curr_x -= char_width( text[i] ); 818 } 819 820 glColor3f( 0.0, 0.0, 0.0 ); 821 glBegin( GL_LINE_LOOP ); 822 /*** 823 glVertex2i( curr_x, y_abs + 4 ); 824 glVertex2i( curr_x, y_abs + 4 ); 825 glVertex2i( curr_x, y_abs + h - 3 ); 826 glVertex2i( curr_x, y_abs + h - 3 ); 827 ***/ 828 curr_x -= x_abs; 829 glVertex2i( curr_x, 0 + 4 ); 830 glVertex2i( curr_x, 0 + 4 ); 831 glVertex2i( curr_x, 0 + h - 3 ); 832 glVertex2i( curr_x, 0 + h - 3 ); 833 glEnd(); 834 835 if ( debug ) dump( stdout, "-> DRAW_INS_PT" ); 836 } 837 838 839 840 /******************************** GLUI_EditText::substring_width() *********/ 841 842 int GLUI_EditText::substring_width( int start, int end ) 843 { 844 int i, width; 845 846 width = 0; 847 848 for( i=start; i<=end; i++ ) 849 width += char_width( text[i] ); 850 851 return width; 852 } 853 854 855 /***************************** GLUI_EditText::update_and_draw_text() ********/ 856 857 void GLUI_EditText::update_and_draw_text( void ) 858 { 859 if ( NOT can_draw() ) 860 return; 861 862 update_substring_bounds(); 863 /* printf( "ss: %d/%d\n", substring_start, substring_end ); */ 864 865 redraw(); 866 } 867 868 869 /********************************* GLUI_EditText::special_handler() **********/ 870 871 int GLUI_EditText::special_handler( int key,int modifiers ) 872 { 873 if ( NOT glui ) 874 return false; 875 876 if ( debug ) 877 printf( "SPECIAL:%d - mod:%d subs:%d/%d ins:%d sel:%d/%d\n", 878 key, modifiers, substring_start, substring_end,insertion_pt, 879 sel_start, sel_end ); 880 881 if ( key == GLUT_KEY_LEFT ) { 882 if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { 883 insertion_pt = find_word_break( insertion_pt, -1 ); 884 } 885 else { 886 insertion_pt--; 887 } 888 } 889 else if ( key == GLUT_KEY_RIGHT ) { 890 if ( (modifiers & GLUT_ACTIVE_CTRL) != 0 ) { 891 insertion_pt = find_word_break( insertion_pt, +1 ); 892 } 893 else { 894 insertion_pt++; 895 } 896 } 897 else if ( key == GLUT_KEY_HOME ) { 898 insertion_pt = 0; 899 } 900 else if ( key == GLUT_KEY_END ) { 901 insertion_pt = (int) text.length(); 902 } 903 904 /*** Update selection if shift key is down ***/ 905 if ( (modifiers & GLUT_ACTIVE_SHIFT ) != 0 ) 906 sel_end = insertion_pt; 907 else 908 sel_start = sel_end = insertion_pt; 909 910 911 CLAMP( insertion_pt, 0, (int) text.length()); /* Make sure insertion_pt 912 is in bounds */ 913 CLAMP( sel_start, 0, (int) text.length()); /* Make sure insertion_pt 914 is in bounds */ 915 CLAMP( sel_end, 0, (int) text.length()); /* Make sure insertion_pt 916 is in bounds */ 917 proto_reg_handoff_h225(void)918 /******** Now redraw text ***********/ 919 if ( can_draw()) 920 update_and_draw_text(); 921 922 return true; 923 } 924 925 926 /****************************** GLUI_EditText::find_word_break() **********/ 927 /* It looks either left or right (depending on value of 'direction' */ 928 /* for the beginning of the next 'word', where word are characters */ 929 /* separated by one of the following tokens: " :-.," */ 930 /* If there is no next word in the specified direction, this returns */ 931 /* the beginning of 'text', or the very end. */ 932 933 int GLUI_EditText::find_word_break( int start, int direction ) 934 { 935 int i, j; 936 char *breaks = " :-.,"; 937 int num_break_chars = (int)strlen(breaks), text_len = (int)text.length(); 938 int new_pt; 939 940 /** If we're moving left, we have to start two back, in case we're either create_h225_packet_info(packet_info * pinfo)941 already at the beginning of a word, or on a separating token. 942 Otherwise, this function would just return the word we're already at **/ 943 if ( direction == -1 ) { 944 start -= 2; 945 } 946 947 /***** Iterate over text in the specified direction *****/ 948 for ( i=start; i >= 0 AND i < text_len; i += direction ) { 949 950 /** For each character in text, iterate over list of separating tokens **/ 951 for( j=0; j<num_break_chars; j++ ) { 952 if ( text[i] == breaks[j] ) { 953 954 /** character 'i' is a separating token, so we return i+1 **/ 955 new_pt = i + 1; 956 957 CLAMP( new_pt, 0, text_len ); 958 959 return new_pt; 960 } 961 } 962 } 963 964 if ( direction > 0 ) /* Return the end of string */ 965 return text_len; 966 else /* Return the beginning of the text */ 967 return 0; 968 } 969 970 971 /********************************** GLUI_EditText::clear_substring() ********/ 972 973 void GLUI_EditText::clear_substring( int start, int end ) 974 { 975 int i; 976 977 /* 978 printf( "clearing: %d-%d '", start,end); 979 for(i=start;i<end;i++ ) 980 putchar(text[i]); ras_call_matching(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,h225_packet_info * pi)981 printf( "'\n" ); flushout; 982 */ 983 /*** See if we're deleting a period in a float data-type box ***/ 984 if ( data_type == GLUI_EDITTEXT_FLOAT ) { 985 for( i=start; i<end; i++ ) 986 if ( text[i] == '.' ) 987 num_periods = 0; 988 } 989 990 text.erase(start,end-start); 991 } 992 993 994 995 /************************************ GLUI_EditText::update_size() **********/ 996 997 void GLUI_EditText::update_size( void ) 998 { 999 int text_size, delta; 1000 1001 if ( NOT glui ) 1002 return; 1003 1004 text_size = string_width( name ); 1005 1006 delta = 0; 1007 if ( text_x_offset < text_size +2 ) 1008 delta = text_size+2-text_x_offset; 1009 1010 text_x_offset += delta; 1011 /* w += delta; */ 1012 1013 if ( data_type == GLUI_EDITTEXT_TEXT OR 1014 data_type == GLUI_EDITTEXT_FLOAT) { 1015 if ( w < text_x_offset + GLUI_EDITTEXT_MIN_TEXT_WIDTH ) 1016 w = text_x_offset + GLUI_EDITTEXT_MIN_TEXT_WIDTH; 1017 } 1018 else if ( data_type == GLUI_EDITTEXT_INT ) { 1019 if ( w < text_x_offset + GLUI_EDITTEXT_MIN_INT_WIDTH ) 1020 w = text_x_offset + GLUI_EDITTEXT_MIN_INT_WIDTH; 1021 } 1022 } 1023 1024 1025 /****************************** GLUI_EditText::set_text() **********/ 1026 1027 void GLUI_EditText::set_text( const char *new_text ) 1028 { 1029 text=new_text; 1030 substring_start = 0; 1031 substring_end = (int) text.length() - 1; 1032 insertion_pt = -1; 1033 sel_start = 0; 1034 sel_end = 0; 1035 1036 if ( can_draw() ) 1037 update_and_draw_text(); 1038 1039 /** Update the spinner, if we have one **/ 1040 if ( spinner ) { 1041 spinner->float_val = this->float_val; 1042 spinner->int_val = this->int_val; 1043 } 1044 1045 /*** Now update the live variable ***/ 1046 output_live(true); 1047 } 1048 1049 1050 /******************************* GLUI_EditText::set_float_val() ************/ 1051 1052 void GLUI_EditText::set_float_val( float new_val ) 1053 { 1054 if ( has_limits == GLUI_LIMIT_CLAMP ) { 1055 /*** Clamp the new value to the existing limits ***/ 1056 1057 CLAMP( new_val, float_low, float_high ); 1058 } 1059 else if ( has_limits == GLUI_LIMIT_WRAP ) { 1060 /*** Clamp the value cyclically to the limits - that is, if the 1061 value exceeds the max, set it the the minimum, and conversely ***/ 1062 1063 if ( new_val < float_low ) 1064 new_val = float_high; 1065 if ( new_val > float_high ) 1066 new_val = float_low; 1067 } 1068 1069 float_val = new_val; 1070 int_val = (int) new_val; /* Mirror the value as an int, too */ 1071 1072 set_numeric_text(); 1073 } 1074 1075 1076 /********************************** GLUI_EditText::set_int_val() ************/ 1077 1078 void GLUI_EditText::set_int_val( int new_val ) 1079 { 1080 if ( has_limits == GLUI_LIMIT_CLAMP ) { 1081 /*** Clamp the new value to the existing limits ***/ 1082 1083 CLAMP( new_val, int_low, int_high ); 1084 } 1085 else if ( has_limits == GLUI_LIMIT_WRAP ) { 1086 /*** Clamp the value cyclically to the limits - that is, if the 1087 value exceeds the max, set it the the minimum, and conversely ***/ 1088 1089 if ( new_val < int_low ) 1090 new_val = int_high; 1091 if ( new_val > int_high ) 1092 new_val = int_low; 1093 } 1094 1095 int_val = new_val; 1096 float_val = (float) new_val; /* We mirror the value as a float, too */ 1097 1098 set_numeric_text(); 1099 } 1100 1101 1102 /********************************* GLUI_EditText::set_float_limits() *********/ 1103 1104 void GLUI_EditText::set_float_limits( float low, float high, int limit_type ) 1105 { 1106 has_limits = limit_type; 1107 float_low = low; 1108 float_high = high; 1109 1110 if ( NOT IN_BOUNDS( float_val, float_low, float_high )) 1111 set_float_val( float_low ); 1112 1113 int_low = (int) float_low; 1114 int_high = (int) float_high; 1115 } 1116 1117 1118 /*********************************** GLUI_EditText::set_int_limits() *********/ 1119 1120 void GLUI_EditText::set_int_limits( int low, int high, int limit_type ) 1121 { 1122 has_limits = limit_type; 1123 int_low = low; 1124 int_high = high; 1125 1126 if ( NOT IN_BOUNDS( int_val, int_low, int_high )) 1127 set_int_val( int_low ); 1128 1129 float_low = (float) int_low; 1130 float_high = (float) int_high; 1131 } 1132 1133 1134 /************************************ GLUI_EditText::set_numeric_text() ******/ 1135 1136 void GLUI_EditText::set_numeric_text( void ) 1137 { 1138 char buf_num[200]; 1139 int i, text_len; 1140 1141 if ( data_type == GLUI_EDITTEXT_FLOAT ) { 1142 sprintf( buf_num, "%#g", float_val ); 1143 1144 num_periods = 0; 1145 text_len = (int) strlen(buf_num); 1146 for ( i=0; i<text_len; i++ ) 1147 if ( buf_num[i] == '.' ) 1148 num_periods++; 1149 1150 /* Now remove trailing zeros */ 1151 if ( num_periods > 0 ) { 1152 text_len = (int) strlen(buf_num); 1153 for ( i=text_len-1; i>0; i-- ) { 1154 if ( buf_num[i] == '0' AND buf_num[i-1] != '.' ) 1155 buf_num[i] = '\0'; 1156 else 1157 break; 1158 } 1159 } 1160 set_text( buf_num ); 1161 } 1162 else { 1163 sprintf( buf_num, "%d", int_val ); 1164 set_text( buf_num ); 1165 } 1166 1167 } 1168 1169 1170 /*************************************** GLUI_EditText::dump() **************/ 1171 1172 void GLUI_EditText::dump( FILE *out, const char *name ) 1173 { 1174 fprintf( out, 1175 "%s (edittext@%p): ins_pt:%d subs:%d/%d sel:%d/%d len:%d\n", 1176 name, this, 1177 insertion_pt, 1178 substring_start, 1179 substring_end, 1180 sel_start, 1181 sel_end, 1182 (int) text.length()); 1183 } 1184 1185 1186 /**************************************** GLUI_EditText::mouse_over() ********/ 1187 1188 int GLUI_EditText::mouse_over( int state, int x, int y ) 1189 { 1190 if ( state ) { 1191 /* curr_cursor = GLUT_CURSOR_TEXT; */ 1192 glutSetCursor( GLUT_CURSOR_TEXT ); 1193 } 1194 else { 1195 /* printf( "OUT\n" ); */ 1196 glutSetCursor( GLUT_CURSOR_LEFT_ARROW ); 1197 } 1198 1199 return true; 1200 } 1201