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(rec->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 dir = dirstat(rechome); 784 if (dir != nil) { 785 if (dir->mode & DMDIR) { 786 free(dir); 787 free(rechome); 788 return 0; 789 } 790 free(dir); 791 } else { 792 int fd; 793 if ((fd = create(rechome, OREAD, DMDIR|0755)) >= 0) { 794 close(fd); 795 free(rechome); 796 return(0); 797 } 798 } 799 free(rechome); 800 return(-1); 801 } 802 803 /* 804 * Constructor functions for making structures. 805 * 806 * The general philosophy here is that we control all memory 807 * in connected data structures, *except* for pen_point arrays. 808 * There are likely to be lots and lots of points, they are likely 809 * to come from the window system; so if we wanted to control them, 810 * we would have to copy which would be slow. We require the client 811 * to deal with them directly, or the client can give us permission 812 * to delete them. 813 */ 814 815 /* 816 * recognizer 817 */ 818 819 820 recognizer make_recognizer(rec_info* rif) 821 { 822 recognizer rec; 823 824 /*Allocate it.*/ 825 826 rec = (recognizer)safe_malloc(sizeof(*rec)); 827 rec->recognizer_magic = REC_MAGIC; 828 rec->recognizer_version = REC_VERSION; 829 rec->recognizer_info = rif; 830 rec->recognizer_specific = nil; 831 rec->recognizer_end_magic = REC_END_MAGIC; 832 rec->recognizer_load_state = nil; 833 rec->recognizer_save_state = nil; 834 rec->recognizer_load_dictionary = nil; 835 rec->recognizer_save_dictionary = nil; 836 rec->recognizer_free_dictionary = nil; 837 rec->recognizer_add_to_dictionary = nil; 838 rec->recognizer_delete_from_dictionary = nil; 839 rec->recognizer_error = nil; 840 rec->recognizer_set_context = nil; 841 rec->recognizer_get_context = nil; 842 rec->recognizer_clear = nil; 843 rec->recognizer_get_buffer = nil; 844 rec->recognizer_set_buffer = nil; 845 rec->recognizer_translate = nil; 846 rec->recognizer_get_extension_functions = nil; 847 rec->recognizer_get_gesture_names = nil; 848 rec->recognizer_set_gesture_action = nil; 849 return(rec); 850 } 851 852 void delete_recognizer(recognizer rec) 853 { 854 855 if( rec != nil ) { 856 if( rec->recognizer_info != nil ) { 857 delete_rec_info(rec->recognizer_info); 858 } 859 free(rec); 860 } 861 } 862 863 /* 864 * rec_alternative 865 */ 866 867 rec_alternative* make_rec_alternative_array(uint size) 868 { 869 int i; 870 rec_alternative* ri; 871 872 ri = (rec_alternative*) safe_malloc(size * sizeof(rec_alternative)); 873 874 for( i = 0; i < size; i++ ) { 875 ri[i].ra_elem.re_type = REC_NONE; 876 ri[i].ra_elem.re_result.aval = nil; 877 ri[i].ra_elem.re_conf = 0; 878 ri[i].ra_nalter = 0; 879 ri[i].ra_next = nil; 880 } 881 882 return(ri); 883 } 884 885 rec_alternative* 886 initialize_rec_alternative(rec_alternative* ra, uint nelm) 887 { 888 if( ra != nil ) { 889 if( (ra->ra_next = make_rec_alternative_array(nelm)) == nil ) { 890 return(nil); 891 } 892 893 ra->ra_nalter = nelm; 894 } 895 896 return(ra); 897 } 898 899 void delete_rec_alternative_array(uint nalter, 900 rec_alternative* ra, 901 bool delete_points_p) 902 { 903 int i; 904 905 if( ra != nil ) { 906 907 for( i = 0; i < nalter; i++ ) { 908 cleanup_rec_element(&ra[i].ra_elem,delete_points_p); 909 910 /*Now do the next one down the line.*/ 911 912 if( ra[i].ra_nalter > 0 ) { 913 delete_rec_alternative_array(ra[i].ra_nalter, 914 ra[i].ra_next, 915 delete_points_p); 916 } 917 } 918 919 free(ra); 920 } 921 } 922 923 924 /*initialize_rec_element-Initialize a recognition element.*/ 925 926 rec_element* 927 initialize_rec_element(rec_element* re, 928 char type, 929 uint size, 930 void* trans, 931 rec_confidence conf) 932 { 933 if( re != nil ) { 934 935 re->re_type = type; 936 re->re_conf = conf; 937 re->re_result.aval = nil; 938 939 switch (type) { 940 941 case REC_GESTURE: 942 if( size > 0 && trans != nil ) { 943 re->re_result.gval = 944 (gesture*)safe_malloc(sizeof(gesture)); 945 memcpy((void*)re->re_result.gval,trans,sizeof(gesture)); 946 } 947 break; 948 949 case REC_ASCII: 950 case REC_VAR: 951 case REC_OTHER: 952 if( size > 0 && trans != nil ) { 953 re->re_result.aval = 954 (char*)safe_malloc((size+1)*sizeof(char)); 955 memcpy((void*)re->re_result.aval,trans,size*sizeof(char)); 956 re->re_result.aval[size] = '\000'; 957 } 958 break; 959 960 case REC_WCHAR: 961 if( size > 0 && trans != nil ) { 962 re->re_result.wval = 963 (wchar_t*)safe_malloc((size+1)*sizeof(wchar_t)); 964 memcpy((void*)re->re_result.wval,trans,size*sizeof(wchar_t)); 965 re->re_result.wval[size] = '\000'; 966 } 967 break; 968 969 case REC_CORR: 970 if( size > 0 && trans != nil ) { 971 re->re_result.rcval = 972 (rec_correlation*)safe_malloc(sizeof(rec_correlation)); 973 memcpy((void*)re->re_result.rcval, 974 trans, 975 sizeof(rec_correlation)); 976 } 977 break; 978 979 default: 980 return(nil); 981 } 982 983 } 984 985 return(re); 986 } 987 988 static void cleanup_rec_element(rec_element* re,bool delete_points_p) 989 { 990 switch(re->re_type) { 991 992 case REC_NONE: 993 break; 994 995 case REC_ASCII: 996 case REC_VAR: 997 case REC_WCHAR: 998 case REC_OTHER: 999 free(re->re_result.aval); 1000 break; 1001 1002 case REC_GESTURE: 1003 delete_gesture_array(1,re->re_result.gval,true); 1004 break; 1005 1006 case REC_CORR: 1007 delete_rec_correlation(re->re_result.rcval, 1008 delete_points_p); 1009 break; 1010 1011 } 1012 1013 } 1014 1015 /* 1016 * rec_correlation 1017 */ 1018 1019 1020 rec_correlation* 1021 make_rec_correlation(char type, 1022 uint size, 1023 void* trans, 1024 rec_confidence conf, 1025 uint ps_size) 1026 { 1027 rec_correlation* rc; 1028 1029 rc = (rec_correlation*)safe_malloc(sizeof(rec_correlation)); 1030 1031 rc->ro_nstrokes = ps_size; 1032 1033 /*First initialize element.*/ 1034 1035 if( initialize_rec_element(&(rc->ro_elem), 1036 type, 1037 size, 1038 trans, 1039 conf) == nil ) { 1040 return(nil); 1041 } 1042 1043 if( (rc->ro_strokes = make_Stroke_array(ps_size)) == nil ) { 1044 return(nil); 1045 } 1046 1047 rc->ro_start = (uint*)safe_malloc(ps_size * sizeof(int)); 1048 rc->ro_stop = (uint*)safe_malloc(ps_size * sizeof(int)); 1049 return(rc); 1050 } 1051 1052 void delete_rec_correlation(rec_correlation* rc,bool delete_points_p) 1053 { 1054 if( rc != nil ) { 1055 1056 cleanup_rec_element(&rc->ro_elem,delete_points_p); 1057 1058 delete_Stroke_array(rc->ro_nstrokes,rc->ro_strokes,delete_points_p); 1059 1060 if( rc->ro_start != nil ) { 1061 free(rc->ro_start); 1062 } 1063 1064 if( rc->ro_stop != nil ) { 1065 free(rc->ro_stop); 1066 } 1067 1068 free(rc); 1069 } 1070 1071 } 1072 1073 1074 /* 1075 * rec_fn 1076 */ 1077 1078 1079 rec_fn* make_rec_fn_array(uint size) 1080 { 1081 rec_fn* ri = (rec_fn*)safe_malloc((size + 1) * sizeof(rec_fn)); 1082 int i; 1083 1084 for( i = 0; i < size; i++ ) { 1085 ri[i] = nil; 1086 } 1087 1088 ri[i] = nil; 1089 1090 return(ri); 1091 } 1092 1093 void delete_rec_fn_array(rec_fn* rf) 1094 { 1095 if( rf != nil ) { 1096 free(rf); 1097 } 1098 } 1099 1100 /* 1101 * Stroke 1102 */ 1103 1104 1105 Stroke* make_Stroke_array(uint size) 1106 { 1107 int i; 1108 Stroke* ri; 1109 1110 ri = (Stroke*) safe_malloc(size * sizeof(Stroke)); 1111 for( i = 0; i < size; i++ ) { 1112 ri[i].npts = 0; 1113 ri[i].pts = nil; 1114 } 1115 1116 return(ri); 1117 } 1118 1119 Stroke* initialize_Stroke(Stroke* ps, 1120 uint npts, 1121 pen_point* pts) 1122 { 1123 if( ps != nil ) { 1124 ps->npts = npts; 1125 ps->pts = pts; 1126 } 1127 return (ps); 1128 } 1129 1130 void delete_Stroke_array(uint size,Stroke* ps,bool delete_points_p) 1131 { 1132 int i; 1133 1134 if( ps != nil ) { 1135 1136 for( i = 0; i < size; i++ ) { 1137 if( delete_points_p ) { 1138 delete_pen_point_array(ps[i].pts); 1139 } 1140 } 1141 1142 free(ps); 1143 } 1144 } 1145 1146 /* 1147 * pen_point 1148 */ 1149 1150 void delete_pen_point_array(pen_point* pp) 1151 { 1152 if( pp != nil ) { 1153 free(pp); 1154 } 1155 } 1156 1157 /* 1158 * gesture 1159 */ 1160 1161 gesture* 1162 make_gesture_array(uint size) 1163 { 1164 return((gesture*)safe_malloc(size * sizeof(gesture))); 1165 } 1166 1167 gesture* initialize_gesture(gesture* g, 1168 char* name, 1169 uint nhs, 1170 pen_point* hspots, 1171 pen_rect bbox, 1172 xgesture fn, 1173 void* wsinfo) 1174 { 1175 if( g != nil ) { 1176 1177 /*We don't do points, 'cause they come from the window system.*/ 1178 1179 g->g_nhs = nhs; 1180 g->g_hspots = hspots; 1181 1182 g->g_name = strdup(name); 1183 1184 g->g_bbox = bbox; 1185 g->g_action = fn; 1186 g->g_wsinfo = wsinfo; 1187 } 1188 return(g); 1189 } 1190 1191 void 1192 delete_gesture_array(uint size,gesture* ga,bool delete_points_p) 1193 { 1194 int i; 1195 1196 if( ga != nil ) { 1197 1198 for( i = 0; i < size; i++ ) { 1199 1200 free(ga[i].g_name); 1201 1202 if( delete_points_p ) { 1203 delete_pen_point_array(ga[i].g_hspots); 1204 } 1205 } 1206 1207 free(ga); 1208 } 1209 } 1210 1211 /* 1212 * copy fns for stroke buffer management. 1213 */ 1214 1215 static Stroke* 1216 copy_Stroke(Stroke* ps1,Stroke* ps2) 1217 { 1218 initialize_Stroke(ps1, 1219 ps2->npts, 1220 ps2->pts); 1221 return(ps1); 1222 1223 } 1224 1225 Stroke* 1226 copy_Stroke_array(uint nstrokes, 1227 Stroke* strokes) 1228 { 1229 int i; 1230 Stroke* ps = make_Stroke_array(nstrokes); 1231 1232 if( ps != nil ) { 1233 1234 for( i = 0; i < nstrokes; i++ ) { 1235 1236 copy_Stroke(&ps[i],&strokes[i]); 1237 1238 } 1239 1240 } 1241 1242 return(ps); 1243 } 1244 1245 uint* 1246 copy_state_trans_array(uint ntrans,uint* trans) 1247 { 1248 uint* pt = (uint*)safe_malloc(ntrans*sizeof(uint)); 1249 int i; 1250 1251 for( i = 0; i < ntrans; i++ ) { 1252 pt[i] = trans[i]; 1253 } 1254 return(pt); 1255 1256 } 1257 1258 Stroke* 1259 concatenate_Strokes(int nstrokes1, 1260 Stroke* strokes1, 1261 int nstrokes2, 1262 Stroke* strokes2, 1263 int* nstrokes3, 1264 Stroke** strokes3) 1265 { 1266 int i; 1267 int ns; 1268 Stroke* ps; 1269 1270 /*Measure new strokes*/ 1271 1272 ns = nstrokes1 + nstrokes2; 1273 1274 /*Allocate memory*/ 1275 1276 if( (ps = make_Stroke_array(ns)) == nil ) { 1277 return(nil); 1278 } 1279 1280 /*Copy old ones into new.*/ 1281 1282 for( i = 0; i < nstrokes1; i++ ) { 1283 if( copy_Stroke(&ps[i],&strokes1[i]) == nil ) { 1284 delete_Stroke_array(ns,ps,false); 1285 return(nil); 1286 } 1287 } 1288 1289 for( ; i < ns; i++ ) { 1290 if( copy_Stroke(&ps[i],&strokes2[i - nstrokes1]) == nil ) { 1291 delete_Stroke_array(ns,ps,false); 1292 return(nil); 1293 } 1294 } 1295 1296 *nstrokes3 = ns; 1297 *strokes3 = ps; 1298 1299 return(ps); 1300 } 1301