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