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
safe_malloc(int nbytes)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
recognizer_load(char * directory,char * name,char ** subset)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
recognizer_unload(recognizer rec)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
recognizer_load_state(recognizer rec,char * dir,char * name)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
recognizer_save_state(recognizer rec,char * dir,char * name)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
recognizer_load_dictionary(recognizer rec,char * dir,char * name)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
recognizer_save_dictionary(recognizer rec,char * dir,char * name,wordset dict)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
recognizer_free_dictionary(recognizer rec,wordset dict)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
recognizer_add_to_dictionary(recognizer rec,letterset * word,wordset dict)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
recognizer_delete_from_dictionary(recognizer rec,letterset * word,wordset dict)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*
recognizer_get_info(recognizer rec)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
recognizer_manager_version(recognizer rec)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
recognizer_error(recognizer rec)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
recognizer_set_context(recognizer rec,rc * rec_xt)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
recognizer_get_context(recognizer rec)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
recognizer_clear(recognizer rec,bool delete_points_p)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
recognizer_get_buffer(recognizer rec,uint * nstrokes,Stroke ** strokes)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
recognizer_set_buffer(recognizer rec,uint nstrokes,Stroke * strokes)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
recognizer_translate(recognizer rec,uint nstrokes,Stroke * strokes,bool correlate_p,int * nret,rec_alternative ** ret)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
recognizer_get_extension_functions(recognizer rec)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**
recognizer_get_gesture_names(recognizer rec)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
recognizer_train_gestures(recognizer rec,char * name,xgesture fn,void * wsinfo)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
shared_library_name(char * directory,char * locale,char * name)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
intl_initialize(void)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
make_rec_info(char *,char *,char ** subset)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
delete_rec_info(rec_info * ri)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
check_for_user_home()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
make_recognizer(rec_info * rif)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
delete_recognizer(recognizer rec)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
make_rec_alternative_array(uint size)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*
initialize_rec_alternative(rec_alternative * ra,uint nelm)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
delete_rec_alternative_array(uint nalter,rec_alternative * ra,bool delete_points_p)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*
initialize_rec_element(rec_element * re,char type,uint size,void * trans,rec_confidence conf)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
cleanup_rec_element(rec_element * re,bool delete_points_p)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*
make_rec_correlation(char type,uint size,void * trans,rec_confidence conf,uint ps_size)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
delete_rec_correlation(rec_correlation * rc,bool delete_points_p)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
make_rec_fn_array(uint size)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
delete_rec_fn_array(rec_fn * rf)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
make_Stroke_array(uint size)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
initialize_Stroke(Stroke * ps,uint npts,pen_point * pts)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
delete_Stroke_array(uint size,Stroke * ps,bool delete_points_p)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
delete_pen_point_array(pen_point * pp)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*
make_gesture_array(uint size)1162 make_gesture_array(uint size)
1163 {
1164 return((gesture*)safe_malloc(size * sizeof(gesture)));
1165 }
1166
initialize_gesture(gesture * g,char * name,uint nhs,pen_point * hspots,pen_rect bbox,xgesture fn,void * wsinfo)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
delete_gesture_array(uint size,gesture * ga,bool delete_points_p)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*
copy_Stroke(Stroke * ps1,Stroke * ps2)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*
copy_Stroke_array(uint nstrokes,Stroke * strokes)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*
copy_state_trans_array(uint ntrans,uint * trans)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*
concatenate_Strokes(int nstrokes1,Stroke * strokes1,int nstrokes2,Stroke * strokes2,int * nstrokes3,Stroke ** strokes3)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