comparison packages/services/gfx/mw/current/src/demos/nxscribble/hre_api.c @ 208:e0c0827131d1 ecos

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