1 /* 2 * hre_api.c: Implementation of HRE API 3 * Author: James & 4 * Created On: Wed Dec 9 13:49:14 1992 5 * Last Modified By: James Kempf 6 * Last Modified On: Fri Sep 23 13:49:04 1994 7 * Update Count: 137 8 * Copyright (c) 1994 by Sun Microsystems Computer Company 9 * All rights reserved. 10 * 11 * Use and copying of this software and preparation of 12 * derivative works based upon this software are permitted. 13 * Any distribution of this software or derivative works 14 * must comply with all applicable United States export control 15 * laws. 16 * 17 * This software is made available as is, and Sun Microsystems 18 * Computer Company makes no warranty about the software, its 19 * performance, or its conformity to any specification 20 */ 21 22 #include <u.h> 23 #include <libc.h> 24 #include <draw.h> 25 #include <scribble.h> 26 27 #include "scribbleimpl.h" 28 #include "hre_internal.h" 29 30 /* ari -- prototype for rii function */ 31 recognizer __recognizer_internal_initialize(rec_info* ri); 32 33 /*Version number of API.*/ 34 35 char* REC_VERSION = "2.0"; 36 37 /*Domain name for internationalized text.*/ 38 39 #define INTL_DOMAIN "recognition_manager" 40 41 /* XXX -- Intl Hack -- Jay & Ari */ 42 #define dgettext(domain, msg) (msg) 43 #define bindtextdomain(dirname, domain) 44 45 /* 46 * These magic numbers are used to ensure the integrity of the 47 * recognizer structure. 48 */ 49 50 51 #define REC_MAGIC 0xfeed 52 #define REC_END_MAGIC 0xbeef 53 54 /*Check the recognizer for validity*/ 55 56 #define RI_CHECK_MAGIC(rec) \ 57 ( (rec != nil) && \ 58 (((recognizer)rec)->recognizer_magic == REC_MAGIC) && \ 59 (((recognizer)rec)->recognizer_end_magic == REC_END_MAGIC) &&\ 60 (((recognizer)rec)->recognizer_version == REC_VERSION) ) 61 62 /*The name of the initialization & finalization functions.*/ 63 64 /* static char rii_name[] = "__recognizer_internal_initialize"; 65 static char rif_name[] = "__recognizer_internal_finalize"; */ 66 67 /*User home directory for recognizer info.*/ 68 /* ari -- changed USERRECHOME from ".recognizers" */ 69 #define HOME "HOME" 70 #define USERRECHOME ".classifiers" 71 72 /*Local functions*/ 73 74 static char* shared_library_name(char* directory,char* locale,char* name); 75 static rec_info* make_rec_info(char* directory,char* name,char** subset); 76 static void delete_rec_info(rec_info* ri); 77 static int check_for_user_home(void); 78 static void intl_initialize(void); 79 80 static void cleanup_rec_element(rec_element* re,bool delete_points_p); 81 82 /*The last error.*/ 83 84 static char* the_last_error = nil; 85 86 static char *safe_malloc (int nbytes) 87 { 88 char *res = malloc(nbytes); 89 if (res == nil) { 90 sysfatal("malloc failure"); 91 } 92 return (res); 93 } 94 95 96 /* 97 * Implementation of API functions 98 */ 99 100 /* 101 * recognizer_load - Load the recognizer matching the rec_info struct. 102 * If name is not null, then load the recognizer having that name. Returns 103 * the recognizer object, or null if it can't load the recognizer, and 104 * sets errno to indicate why. 105 */ 106 107 recognizer 108 recognizer_load(char* directory, char* name, char** subset) 109 { 110 recognizer rec; /*the recognizer*/ 111 rec_info* rinf; /*rec_info for recognizer information*/ 112 static bool intl_init = false; /*true if recog. manager initted.*/ 113 114 if( intl_init == false ) { 115 intl_init = true; 116 intl_initialize(); 117 } 118 119 /*The name takes precedence.*/ 120 rinf = make_rec_info(directory, name, subset); 121 if (rinf == nil) { 122 the_last_error = 123 dgettext(INTL_DOMAIN, 124 "Ran out of memory during prelinking initialization."); 125 return((recognizer)nil); 126 } 127 /* fprint(2, "Got past make_rec_info.\n"); */ 128 129 /*Let recognition code create recognizer and initialize*/ 130 rec = __recognizer_internal_initialize(rinf); 131 if (rec == nil) { 132 return((recognizer)nil); 133 } 134 /* fprint(2, "Did rii.\n"); */ 135 /*Check whether it's been correctly initialized*/ 136 137 if( rec->recognizer_load_state == nil || 138 rec->recognizer_save_state == nil || 139 rec->recognizer_load_dictionary == nil || 140 rec->recognizer_save_dictionary == nil || 141 rec->recognizer_free_dictionary == nil || 142 rec->recognizer_add_to_dictionary == nil || 143 rec->recognizer_delete_from_dictionary == nil || 144 rec->recognizer_error == nil || 145 rec->recognizer_set_context == nil || 146 rec->recognizer_get_context == nil || 147 rec->recognizer_clear == nil || 148 rec->recognizer_get_buffer == nil || 149 rec->recognizer_set_buffer == nil || 150 rec->recognizer_translate == nil || 151 rec->recognizer_get_extension_functions == nil || 152 rec->recognizer_get_gesture_names == nil || 153 rec->recognizer_set_gesture_action == nil 154 ) { 155 156 recognizer_unload(rec); 157 /* fprint(2, "Unloading b/c null function pointer.\n"); */ 158 the_last_error = 159 dgettext(INTL_DOMAIN, 160 "One or more recognizer function pointers is nil."); 161 return((recognizer)nil); 162 } 163 164 165 /*Set the rec_info structure.*/ 166 167 rec->recognizer_info = rinf; 168 169 /*Check whether home directory is there for recognizer info.*/ 170 171 /* 172 * ari -- don't bother. We're not going to load from each user's 173 * home directory at this point. Instead, we'll use a stupid 174 * little a-b-c file because it loads FAST. 175 * 176 * if( check_for_user_home() < 0 ) { 177 * recognizer_unload(rec); 178 * return((recognizer)nil); 179 * } 180 */ 181 /*We got it!*/ 182 /* fprint(2, "Done.\n"); */ 183 184 return(rec); 185 } 186 187 /* 188 * recognizer_unload - Unload the recognizer. 189 */ 190 191 int 192 recognizer_unload(recognizer rec) 193 { 194 /*Make sure magic numbers right.*/ 195 196 if( !RI_CHECK_MAGIC(rec) ) { 197 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 198 return(-1); 199 } 200 201 return __recognizer_internal_finalize(rec); 202 } 203 204 /* 205 * recognizer_load_state-Get any recognizer state associated with name 206 * in dir. Note that name may not be simple file name, since 207 * there may be more than one file involved. Return 0 if successful, 208 * -1 if not. 209 */ 210 211 int recognizer_load_state(recognizer rec, char* dir, char* name) 212 { 213 /*Make sure magic numbers right.*/ 214 215 if( !RI_CHECK_MAGIC(rec) ) { 216 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 217 return(-1); 218 } 219 220 /*Do the function.*/ 221 222 return(rec->recognizer_load_state(rec, dir, name)); 223 } 224 225 /* 226 * recognizer_save_state-Save any recognizer state to name 227 * in dir. Note that name may not be a simple file name, since 228 * there may be more than one file involved. Return 0 if successful, 229 * -1 if not. 230 */ 231 232 int recognizer_save_state(recognizer rec,char* dir,char* name) 233 { 234 /*Make sure magic numbers right.*/ 235 236 if( !RI_CHECK_MAGIC(rec) ) { 237 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 238 return(-1); 239 } 240 241 /*Do the function.*/ 242 243 return(rec->recognizer_save_state(rec,dir,name)); 244 } 245 246 /* 247 * recognizer_load_dictionary-Load dictionary, return pointer 248 * to it, or nil if error. 249 */ 250 251 wordset recognizer_load_dictionary(recognizer rec,char* dir,char* name) 252 { 253 /*Make sure magic numbers right.*/ 254 255 if( !RI_CHECK_MAGIC(rec) ) { 256 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 257 return(nil); 258 } 259 260 /*Do the function.*/ 261 262 return(rec->recognizer_load_dictionary(rec,dir,name)); 263 } 264 265 /* 266 * recognizer_save_dictionary-Save the dictionary to the file, return 0 if 267 * OK, -1 if error. 268 */ 269 270 int recognizer_save_dictionary(recognizer rec,char* dir,char* name,wordset dict) 271 { 272 /*Make sure magic numbers right.*/ 273 274 if( !RI_CHECK_MAGIC(rec) ) { 275 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 276 return(-1); 277 } 278 279 /*Do the function.*/ 280 281 return(rec->recognizer_save_dictionary(rec,dir,name,dict)); 282 } 283 284 /* 285 * recognizer_free_dictionary-Free the dictionary, return 0 if 286 * OK, -1 if error. 287 */ 288 289 int recognizer_free_dictionary(recognizer rec,wordset dict) 290 { 291 /*Make sure magic numbers right.*/ 292 293 if( !RI_CHECK_MAGIC(rec) ) { 294 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 295 return(-1); 296 } 297 298 /*Do the function.*/ 299 300 return(rec->recognizer_free_dictionary(rec,dict)); 301 } 302 303 /* 304 * recognizer_add_to_dictionary-Add word to the dictionary, 305 * return 0 if OK, -1 if error. 306 */ 307 308 309 int recognizer_add_to_dictionary(recognizer rec,letterset* word,wordset dict) 310 { 311 /*Make sure magic numbers right.*/ 312 313 if( !RI_CHECK_MAGIC(rec) ) { 314 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 315 return(-1); 316 } 317 318 /*Do the function.*/ 319 320 return(rec->recognizer_add_to_dictionary(rec,word,dict)); 321 } 322 323 /* 324 * recognizer_delete_from_dictionary-Delete word from the dictionary, 325 * return 0 if OK, -1 if error. 326 */ 327 328 int 329 recognizer_delete_from_dictionary(recognizer rec,letterset* word,wordset dict) 330 { 331 /*Make sure magic numbers right.*/ 332 333 if( !RI_CHECK_MAGIC(rec) ) { 334 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 335 return(-1); 336 } 337 338 /*Do the function.*/ 339 340 return(rec->recognizer_delete_from_dictionary(rec,word,dict)); 341 } 342 343 /* 344 * recognizer_get_info-Get a pointers to the rec_info 345 * giving the locales and subsets supported by the recognizer 346 * and the shared library pathname. 347 */ 348 349 const rec_info* 350 recognizer_get_info(recognizer rec) 351 { 352 /*Make sure magic numbers right.*/ 353 354 if( !RI_CHECK_MAGIC(rec) ) { 355 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 356 return((rec_info*)nil); 357 } 358 359 /*Return the rec_info object.*/ 360 361 return(rec->recognizer_info); 362 } 363 364 /* 365 * recognizer_manager_version-Return the version number string of the 366 * recognition manager. 367 */ 368 369 const char* recognizer_manager_version(recognizer rec) 370 { 371 /*Make sure magic numbers right.*/ 372 373 if( !RI_CHECK_MAGIC(rec) ) { 374 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 375 return(nil); 376 } 377 378 return(rec->recognizer_version); 379 380 } 381 /* 382 * recognizer_error-Return the last error message, or nil if none. 383 */ 384 385 char* recognizer_error(recognizer rec) 386 { 387 388 /*Make sure magic numbers right and function there.*/ 389 390 if( !RI_CHECK_MAGIC(rec) && the_last_error == nil ) { 391 return(dgettext(INTL_DOMAIN,"Bad recognizer object.")); 392 393 } else if( the_last_error != nil ) { 394 char* error = the_last_error; 395 396 the_last_error = nil; 397 return(error); 398 } 399 400 /*Do the function.*/ 401 402 return(rec->recognizer_error(rec)); 403 } 404 405 /* 406 * recognizer_set_context-Set the recognition context for translation. 407 * Return 0 if successful, -1 if error. 408 */ 409 410 int recognizer_set_context(recognizer rec,rc* rec_xt) 411 { 412 413 /*Make sure magic numbers right.*/ 414 415 if( !RI_CHECK_MAGIC(rec) ) { 416 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 417 return(-1); 418 } 419 420 /*Do the function.*/ 421 422 return(rec->recognizer_set_context(rec,rec_xt)); 423 } 424 425 /* 426 * recognzier_get_context-Get the recognition context for translation. 427 * If none or error, return nil. 428 */ 429 430 rc* recognizer_get_context(recognizer rec) 431 { 432 433 /*Make sure magic numbers right.*/ 434 435 if( !RI_CHECK_MAGIC(rec) ) { 436 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 437 return(nil); 438 } 439 440 /*Do the function.*/ 441 442 return(recognizer_get_context(rec)); 443 } 444 445 /* 446 * recognizer_clear-Clear buffer and recognition context. 447 * Return 0 if success, else -1. 448 */ 449 450 int recognizer_clear(recognizer rec,bool delete_points_p) 451 { 452 453 /*Make sure magic numbers right.*/ 454 455 if( !RI_CHECK_MAGIC(rec) ) { 456 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 457 return(-1); 458 } 459 460 /*Do the function.*/ 461 462 return(rec->recognizer_clear(rec,delete_points_p)); 463 } 464 465 /*recognizer_get_buffer-Get stroke buffer. Return 0 if success, else -1.*/ 466 467 468 int recognizer_get_buffer(recognizer rec, uint* nstrokes,Stroke** strokes) 469 { 470 471 /*Make sure magic numbers right.*/ 472 473 if( !RI_CHECK_MAGIC(rec) ) { 474 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 475 return(-1); 476 } 477 478 /*Do the function.*/ 479 480 return(rec->recognizer_get_buffer(rec,nstrokes,strokes)); 481 482 } 483 484 /* 485 * recognizer_set_buffer-Set stroke buffer to arg. Return 0 if success, else 486 * return -1. 487 */ 488 489 int recognizer_set_buffer(recognizer rec,uint nstrokes,Stroke* strokes) 490 { 491 492 /*Make sure magic numbers right.*/ 493 494 if( !RI_CHECK_MAGIC(rec) ) { 495 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 496 return(-1); 497 } 498 499 /*Do the function.*/ 500 501 return(rec->recognizer_set_buffer(rec,nstrokes,strokes)); 502 503 } 504 505 /* 506 * recognizer_translate-Translate the strokes in the current context, including 507 * buffered strokes. If nstrokes == 0 or strokes == nil, return 508 * translation of stroke buffer. 509 */ 510 511 int recognizer_translate(recognizer rec, 512 uint nstrokes, 513 Stroke* strokes, 514 bool correlate_p, 515 int* nret, 516 rec_alternative** ret) 517 { 518 int retval; 519 char msg[80]; 520 /*Make sure magic numbers right.*/ 521 522 if( !RI_CHECK_MAGIC(rec) ) { 523 the_last_error = dgettext(INTL_DOMAIN, msg); 524 return(-1); 525 } 526 527 /* ari */ 528 /* { 529 * uint i; 530 * Stroke ari_pstr; 531 * pen_point* ari_pts; 532 * int ari; 533 * for (i = 0; i < nstrokes; i++) { 534 * ari_pstr = strokes[i]; 535 * ari_pts = ari_pstr.ps_pts; 536 * fprint(2, "\nrecognizer_translate: ari_pts = %ld, sizeof(Time) = %d, sizeof(ari_pts[0] = %d, %d points are...\n", ari_pts, sizeof(Time), sizeof(ari_pts[0]), ari_pstr.ps_npts); 537 * for (ari = 0; ari < ari_pstr.ps_npts; ari++) 538 * fprint(2, "%ld -- (%d, %d) ", ari_pts[ari], ari_pts[ari].x, ari_pts[ari].y); 539 * } 540 * } 541 */ 542 /*Do the function.*/ 543 /* ari -- this is calling cmu_recognizer_translate */ 544 retval = rec->recognizer_translate(rec, 545 nstrokes, 546 strokes, 547 correlate_p, 548 nret, 549 ret); 550 return (retval); 551 } 552 553 554 /* 555 * recognizer_get_extension_functions-Return a null terminated array 556 * of functions providing extended functionality. Their interfaces 557 * will change depending on the recognizer. 558 */ 559 560 rec_fn* recognizer_get_extension_functions(recognizer rec) 561 { 562 /*Make sure magic numbers right.*/ 563 564 if( !RI_CHECK_MAGIC(rec) ) { 565 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 566 return((rec_fn*)nil); 567 } 568 569 /*Do the function.*/ 570 571 return(rec->recognizer_get_extension_functions(rec)); 572 } 573 574 575 /* 576 * recognizer_get_gesture_names - Return a null terminated array of 577 * gesture name strings. 578 */ 579 580 char** 581 recognizer_get_gesture_names(recognizer rec) 582 { 583 /*Make sure magic numbers right.*/ 584 585 if( !RI_CHECK_MAGIC(rec) ) { 586 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 587 return(nil); 588 } 589 590 /*Do the function.*/ 591 592 return(rec->recognizer_get_gesture_names(rec)); 593 } 594 595 /* 596 * recognizer_set_gesture_action-Set the action function for the gesture. 597 */ 598 599 xgesture 600 recognizer_train_gestures(recognizer rec,char* name,xgesture fn,void* wsinfo) 601 { 602 /*Make sure magic numbers right.*/ 603 604 if( !RI_CHECK_MAGIC(rec) ) { 605 the_last_error = dgettext(INTL_DOMAIN,"Bad recognizer object."); 606 return((xgesture)-1); 607 } 608 609 /*Do the function.*/ 610 611 return(rec->recognizer_set_gesture_action(rec,name,fn,wsinfo)); 612 } 613 614 /* 615 * Local functions. 616 */ 617 618 /* 619 * shared_library_name-Get the full pathname to the shared library, 620 * based on the recognizer name and the environment. 621 */ 622 623 624 static char* shared_library_name(char* directory,char* locale,char* name) 625 { 626 char* ret; 627 int len = strlen(name); 628 629 /*If directory is there, it takes precedence.*/ 630 631 if( directory != nil ) { 632 ret = (char*)safe_malloc(strlen(directory) + len + 2); 633 strcpy(ret,directory); 634 strcat(ret,"/"); 635 strcat(ret,name); 636 } else { 637 char* dir; 638 639 /*First try the environment variable.*/ 640 641 if( (dir = getenv(RECHOME)) == nil ) { 642 dir = "REC_DEFAULT_HOME_DIR"; 643 644 } 645 646 ret = (char*)safe_malloc(strlen(dir) + strlen(locale) + len + 3); 647 /*Form the pathname.*/ 648 strcpy(ret,dir); 649 strcat(ret,"/"); 650 strcat(ret,locale); 651 strcat(ret,"/"); 652 strcat(ret,name); 653 } 654 655 return(ret); 656 } 657 658 /* 659 * intl_initialize-Initialize the internationaliztion of messages for 660 * the recognition manager. 661 */ 662 663 static void intl_initialize(void) 664 { 665 char* dirname; 666 667 /*Get recognizer home directory name from environment.*/ 668 669 if( (dirname = getenv(RECHOME)) == nil ) { 670 dirname = "REC_DEFAULT_HOME_DIR"; 671 } 672 673 /*Bind the text domain.*/ 674 USED(dirname); 675 bindtextdomain(dirname, INTL_DOMAIN); 676 } 677 678 679 /*make_rec_info-Create a rec_info structure*/ 680 681 static rec_info* make_rec_info(char*, char*, char** subset) 682 { 683 int i,len; 684 rec_info* ri; 685 char* locale; 686 687 ri = (rec_info*)safe_malloc(sizeof(rec_info)); 688 ri->ri_locale = nil; 689 ri->ri_name = nil; 690 ri->ri_subset = nil; 691 692 /*Get locale*/ 693 694 if( (locale = getenv(LANG)) == nil ) { 695 locale = strdup(REC_DEFAULT_LOCALE); 696 } 697 698 if( (ri->ri_locale = strdup(locale)) == nil ) { 699 delete_rec_info(ri); 700 return(nil); 701 } 702 703 /*Get shared library pathname.*/ 704 705 /*Initialize the subset information.*/ 706 707 if( subset != nil ) { 708 709 /*Count the subset strings.*/ 710 711 for( len = 1; subset[len] != nil; len++ ) ; 712 713 /*Copy the subset strings.*/ 714 715 ri->ri_subset = (char**)safe_malloc((len +1)*sizeof(char*)); 716 717 for( i = 0; i < len; i++ ) { 718 if( subset[i] != nil ) { 719 if( (ri->ri_subset[i] = strdup(subset[i])) == nil ) { 720 delete_rec_info(ri); 721 return(nil); 722 } 723 } else { 724 ri->ri_subset[i] = subset[i]; 725 } 726 } 727 728 ri->ri_subset[i] = nil; 729 730 } else { 731 732 ri->ri_subset = nil; 733 } 734 735 return(ri); 736 } 737 738 static void delete_rec_info(rec_info* ri) 739 { 740 if( ri != nil ) { 741 if( ri->ri_locale != nil ) { 742 free(ri->ri_locale); 743 } 744 /* 745 * if( ri->ri_name != nil ) { 746 * free(ri->ri_name); 747 * } 748 */ 749 if( ri->ri_subset != nil ) { 750 int i; 751 for( i = 0; ri->ri_subset[i] != nil; i++) { 752 free(ri->ri_subset[i]); 753 } 754 free(ri->ri_subset); 755 } 756 free(ri); 757 } 758 } 759 760 /*check_for_user_home-Check whether USERRECHOME has been created.*/ 761 762 static int check_for_user_home() 763 { 764 char* homedir = getenv(HOME); 765 char* rechome; 766 Dir dir; 767 768 if( homedir == nil ) { 769 the_last_error = "Home environment variable HOME not set."; 770 return(-1); 771 } 772 773 rechome = (char*)safe_malloc(strlen(homedir) + strlen(USERRECHOME) + 2); 774 775 /*Form name.*/ 776 777 strcpy(rechome,homedir); 778 strcat(rechome,"/"); 779 strcat(rechome,USERRECHOME); 780 781 /*Create directory.*/ 782 783 if (dirstat(rechome, &dir) == 0) { 784 if (dir.mode & CHDIR) { 785 free(rechome); 786 return 0; 787 } 788 } else { 789 int fd; 790 if ((fd = create(rechome, OREAD, CHDIR|0755)) >= 0) { 791 close(fd); 792 free(rechome); 793 return(0); 794 } 795 } 796 free(rechome); 797 return(-1); 798 } 799 800 /* 801 * Constructor functions for making structures. 802 * 803 * The general philosophy here is that we control all memory 804 * in connected data structures, *except* for pen_point arrays. 805 * There are likely to be lots and lots of points, they are likely 806 * to come from the window system; so if we wanted to control them, 807 * we would have to copy which would be slow. We require the client 808 * to deal with them directly, or the client can give us permission 809 * to delete them. 810 */ 811 812 /* 813 * recognizer 814 */ 815 816 817 recognizer make_recognizer(rec_info* rif) 818 { 819 recognizer rec; 820 821 /*Allocate it.*/ 822 823 rec = (recognizer)safe_malloc(sizeof(*rec)); 824 rec->recognizer_magic = REC_MAGIC; 825 rec->recognizer_version = REC_VERSION; 826 rec->recognizer_info = rif; 827 rec->recognizer_specific = nil; 828 rec->recognizer_end_magic = REC_END_MAGIC; 829 rec->recognizer_load_state = nil; 830 rec->recognizer_save_state = nil; 831 rec->recognizer_load_dictionary = nil; 832 rec->recognizer_save_dictionary = nil; 833 rec->recognizer_free_dictionary = nil; 834 rec->recognizer_add_to_dictionary = nil; 835 rec->recognizer_delete_from_dictionary = nil; 836 rec->recognizer_error = nil; 837 rec->recognizer_set_context = nil; 838 rec->recognizer_get_context = nil; 839 rec->recognizer_clear = nil; 840 rec->recognizer_get_buffer = nil; 841 rec->recognizer_set_buffer = nil; 842 rec->recognizer_translate = nil; 843 rec->recognizer_get_extension_functions = nil; 844 rec->recognizer_get_gesture_names = nil; 845 rec->recognizer_set_gesture_action = nil; 846 return(rec); 847 } 848 849 void delete_recognizer(recognizer rec) 850 { 851 852 if( rec != nil ) { 853 if( rec->recognizer_info != nil ) { 854 delete_rec_info(rec->recognizer_info); 855 } 856 free(rec); 857 } 858 } 859 860 /* 861 * rec_alternative 862 */ 863 864 rec_alternative* make_rec_alternative_array(uint size) 865 { 866 int i; 867 rec_alternative* ri; 868 869 ri = (rec_alternative*) safe_malloc(size * sizeof(rec_alternative)); 870 871 for( i = 0; i < size; i++ ) { 872 ri[i].ra_elem.re_type = REC_NONE; 873 ri[i].ra_elem.re_result.aval = nil; 874 ri[i].ra_elem.re_conf = 0; 875 ri[i].ra_nalter = 0; 876 ri[i].ra_next = nil; 877 } 878 879 return(ri); 880 } 881 882 rec_alternative* 883 initialize_rec_alternative(rec_alternative* ra, uint nelm) 884 { 885 if( ra != nil ) { 886 if( (ra->ra_next = make_rec_alternative_array(nelm)) == nil ) { 887 return(nil); 888 } 889 890 ra->ra_nalter = nelm; 891 } 892 893 return(ra); 894 } 895 896 void delete_rec_alternative_array(uint nalter, 897 rec_alternative* ra, 898 bool delete_points_p) 899 { 900 int i; 901 902 if( ra != nil ) { 903 904 for( i = 0; i < nalter; i++ ) { 905 cleanup_rec_element(&ra[i].ra_elem,delete_points_p); 906 907 /*Now do the next one down the line.*/ 908 909 if( ra[i].ra_nalter > 0 ) { 910 delete_rec_alternative_array(ra[i].ra_nalter, 911 ra[i].ra_next, 912 delete_points_p); 913 } 914 } 915 916 free(ra); 917 } 918 } 919 920 921 /*initialize_rec_element-Initialize a recognition element.*/ 922 923 rec_element* 924 initialize_rec_element(rec_element* re, 925 char type, 926 uint size, 927 void* trans, 928 rec_confidence conf) 929 { 930 if( re != nil ) { 931 932 re->re_type = type; 933 re->re_conf = conf; 934 re->re_result.aval = nil; 935 936 switch (type) { 937 938 case REC_GESTURE: 939 if( size > 0 && trans != nil ) { 940 re->re_result.gval = 941 (gesture*)safe_malloc(sizeof(gesture)); 942 memcpy((void*)re->re_result.gval,trans,sizeof(gesture)); 943 } 944 break; 945 946 case REC_ASCII: 947 case REC_VAR: 948 case REC_OTHER: 949 if( size > 0 && trans != nil ) { 950 re->re_result.aval = 951 (char*)safe_malloc((size+1)*sizeof(char)); 952 memcpy((void*)re->re_result.aval,trans,size*sizeof(char)); 953 re->re_result.aval[size] = '\000'; 954 } 955 break; 956 957 case REC_WCHAR: 958 if( size > 0 && trans != nil ) { 959 re->re_result.wval = 960 (wchar_t*)safe_malloc((size+1)*sizeof(wchar_t)); 961 memcpy((void*)re->re_result.wval,trans,size*sizeof(wchar_t)); 962 re->re_result.wval[size] = '\000'; 963 } 964 break; 965 966 case REC_CORR: 967 if( size > 0 && trans != nil ) { 968 re->re_result.rcval = 969 (rec_correlation*)safe_malloc(sizeof(rec_correlation)); 970 memcpy((void*)re->re_result.rcval, 971 trans, 972 sizeof(rec_correlation)); 973 } 974 break; 975 976 default: 977 return(nil); 978 } 979 980 } 981 982 return(re); 983 } 984 985 static void cleanup_rec_element(rec_element* re,bool delete_points_p) 986 { 987 switch(re->re_type) { 988 989 case REC_NONE: 990 break; 991 992 case REC_ASCII: 993 case REC_VAR: 994 case REC_WCHAR: 995 case REC_OTHER: 996 free(re->re_result.aval); 997 break; 998 999 case REC_GESTURE: 1000 delete_gesture_array(1,re->re_result.gval,true); 1001 break; 1002 1003 case REC_CORR: 1004 delete_rec_correlation(re->re_result.rcval, 1005 delete_points_p); 1006 break; 1007 1008 } 1009 1010 } 1011 1012 /* 1013 * rec_correlation 1014 */ 1015 1016 1017 rec_correlation* 1018 make_rec_correlation(char type, 1019 uint size, 1020 void* trans, 1021 rec_confidence conf, 1022 uint ps_size) 1023 { 1024 rec_correlation* rc; 1025 1026 rc = (rec_correlation*)safe_malloc(sizeof(rec_correlation)); 1027 1028 rc->ro_nstrokes = ps_size; 1029 1030 /*First initialize element.*/ 1031 1032 if( initialize_rec_element(&(rc->ro_elem), 1033 type, 1034 size, 1035 trans, 1036 conf) == nil ) { 1037 return(nil); 1038 } 1039 1040 if( (rc->ro_strokes = make_Stroke_array(ps_size)) == nil ) { 1041 return(nil); 1042 } 1043 1044 rc->ro_start = (uint*)safe_malloc(ps_size * sizeof(int)); 1045 rc->ro_stop = (uint*)safe_malloc(ps_size * sizeof(int)); 1046 return(rc); 1047 } 1048 1049 void delete_rec_correlation(rec_correlation* rc,bool delete_points_p) 1050 { 1051 if( rc != nil ) { 1052 1053 cleanup_rec_element(&rc->ro_elem,delete_points_p); 1054 1055 delete_Stroke_array(rc->ro_nstrokes,rc->ro_strokes,delete_points_p); 1056 1057 if( rc->ro_start != nil ) { 1058 free(rc->ro_start); 1059 } 1060 1061 if( rc->ro_stop != nil ) { 1062 free(rc->ro_stop); 1063 } 1064 1065 free(rc); 1066 } 1067 1068 } 1069 1070 1071 /* 1072 * rec_fn 1073 */ 1074 1075 1076 rec_fn* make_rec_fn_array(uint size) 1077 { 1078 rec_fn* ri = (rec_fn*)safe_malloc((size + 1) * sizeof(rec_fn)); 1079 int i; 1080 1081 for( i = 0; i < size; i++ ) { 1082 ri[i] = nil; 1083 } 1084 1085 ri[i] = nil; 1086 1087 return(ri); 1088 } 1089 1090 void delete_rec_fn_array(rec_fn* rf) 1091 { 1092 if( rf != nil ) { 1093 free(rf); 1094 } 1095 } 1096 1097 /* 1098 * Stroke 1099 */ 1100 1101 1102 Stroke* make_Stroke_array(uint size) 1103 { 1104 int i; 1105 Stroke* ri; 1106 1107 ri = (Stroke*) safe_malloc(size * sizeof(Stroke)); 1108 for( i = 0; i < size; i++ ) { 1109 ri[i].npts = 0; 1110 ri[i].pts = nil; 1111 } 1112 1113 return(ri); 1114 } 1115 1116 Stroke* initialize_Stroke(Stroke* ps, 1117 uint npts, 1118 pen_point* pts) 1119 { 1120 if( ps != nil ) { 1121 ps->npts = npts; 1122 ps->pts = pts; 1123 } 1124 return (ps); 1125 } 1126 1127 void delete_Stroke_array(uint size,Stroke* ps,bool delete_points_p) 1128 { 1129 int i; 1130 1131 if( ps != nil ) { 1132 1133 for( i = 0; i < size; i++ ) { 1134 if( delete_points_p ) { 1135 delete_pen_point_array(ps[i].pts); 1136 } 1137 } 1138 1139 free(ps); 1140 } 1141 } 1142 1143 /* 1144 * pen_point 1145 */ 1146 1147 void delete_pen_point_array(pen_point* pp) 1148 { 1149 if( pp != nil ) { 1150 free(pp); 1151 } 1152 } 1153 1154 /* 1155 * gesture 1156 */ 1157 1158 gesture* 1159 make_gesture_array(uint size) 1160 { 1161 return((gesture*)safe_malloc(size * sizeof(gesture))); 1162 } 1163 1164 gesture* initialize_gesture(gesture* g, 1165 char* name, 1166 uint nhs, 1167 pen_point* hspots, 1168 pen_rect bbox, 1169 xgesture fn, 1170 void* wsinfo) 1171 { 1172 if( g != nil ) { 1173 1174 /*We don't do points, 'cause they come from the window system.*/ 1175 1176 g->g_nhs = nhs; 1177 g->g_hspots = hspots; 1178 1179 g->g_name = strdup(name); 1180 1181 g->g_bbox = bbox; 1182 g->g_action = fn; 1183 g->g_wsinfo = wsinfo; 1184 } 1185 return(g); 1186 } 1187 1188 void 1189 delete_gesture_array(uint size,gesture* ga,bool delete_points_p) 1190 { 1191 int i; 1192 1193 if( ga != nil ) { 1194 1195 for( i = 0; i < size; i++ ) { 1196 1197 free(ga[i].g_name); 1198 1199 if( delete_points_p ) { 1200 delete_pen_point_array(ga[i].g_hspots); 1201 } 1202 } 1203 1204 free(ga); 1205 } 1206 } 1207 1208 /* 1209 * copy fns for stroke buffer management. 1210 */ 1211 1212 static Stroke* 1213 copy_Stroke(Stroke* ps1,Stroke* ps2) 1214 { 1215 initialize_Stroke(ps1, 1216 ps2->npts, 1217 ps2->pts); 1218 return(ps1); 1219 1220 } 1221 1222 Stroke* 1223 copy_Stroke_array(uint nstrokes, 1224 Stroke* strokes) 1225 { 1226 int i; 1227 Stroke* ps = make_Stroke_array(nstrokes); 1228 1229 if( ps != nil ) { 1230 1231 for( i = 0; i < nstrokes; i++ ) { 1232 1233 copy_Stroke(&ps[i],&strokes[i]); 1234 1235 } 1236 1237 } 1238 1239 return(ps); 1240 } 1241 1242 uint* 1243 copy_state_trans_array(uint ntrans,uint* trans) 1244 { 1245 uint* pt = (uint*)safe_malloc(ntrans*sizeof(uint)); 1246 int i; 1247 1248 for( i = 0; i < ntrans; i++ ) { 1249 pt[i] = trans[i]; 1250 } 1251 return(pt); 1252 1253 } 1254 1255 Stroke* 1256 concatenate_Strokes(int nstrokes1, 1257 Stroke* strokes1, 1258 int nstrokes2, 1259 Stroke* strokes2, 1260 int* nstrokes3, 1261 Stroke** strokes3) 1262 { 1263 int i; 1264 int ns; 1265 Stroke* ps; 1266 1267 /*Measure new strokes*/ 1268 1269 ns = nstrokes1 + nstrokes2; 1270 1271 /*Allocate memory*/ 1272 1273 if( (ps = make_Stroke_array(ns)) == nil ) { 1274 return(nil); 1275 } 1276 1277 /*Copy old ones into new.*/ 1278 1279 for( i = 0; i < nstrokes1; i++ ) { 1280 if( copy_Stroke(&ps[i],&strokes1[i]) == nil ) { 1281 delete_Stroke_array(ns,ps,false); 1282 return(nil); 1283 } 1284 } 1285 1286 for( ; i < ns; i++ ) { 1287 if( copy_Stroke(&ps[i],&strokes2[i - nstrokes1]) == nil ) { 1288 delete_Stroke_array(ns,ps,false); 1289 return(nil); 1290 } 1291 } 1292 1293 *nstrokes3 = ns; 1294 *strokes3 = ps; 1295 1296 return(ps); 1297 } 1298